From b2edc97a4c7dd0266fdbf3beb7b6185857300de2 Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Tue, 31 Oct 2017 16:04:51 +0800 Subject: [PATCH 001/334] [runtime-fix] getProviderProperties bug --- .../virtual/client/hook/proxies/location/MethodProxies.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/location/MethodProxies.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/location/MethodProxies.java index 7aa156b8e..9edefbb3e 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/location/MethodProxies.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/location/MethodProxies.java @@ -282,7 +282,7 @@ public String getMethodName() { @Override public Object afterCall(Object who, Method method, Object[] args, Object result) throws Throwable { - if (isFakeLocationEnable()) { + if (!isFakeLocationEnable()) { return super.afterCall(who, method, args, result); } try { From 23c02b9e7e26344eb59e8f1b4c7151019f192d65 Mon Sep 17 00:00:00 2001 From: asLody Date: Tue, 31 Oct 2017 17:36:09 +0800 Subject: [PATCH 002/334] [runtime-fix]: fix issue #402. --- .../lib/src/main/java/com/lody/virtual/os/VEnvironment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/os/VEnvironment.java b/VirtualApp/lib/src/main/java/com/lody/virtual/os/VEnvironment.java index be1d1ae51..72a5a4ee9 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/os/VEnvironment.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/os/VEnvironment.java @@ -4,6 +4,7 @@ import android.os.Build; import com.lody.virtual.client.core.VirtualCore; +import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.helper.utils.FileUtils; import com.lody.virtual.helper.utils.VLog; @@ -116,7 +117,7 @@ public static File getDalvikCacheDirectory() { } public static File getOdexFile(String packageName) { - return new File(DALVIK_CACHE_DIRECTORY, "base.odex"); + return new File(DALVIK_CACHE_DIRECTORY, "data@app@" + packageName + "-1@base.apk@classes.dex"); } public static File getDataAppPackageDirectory(String packageName) { From 0359798f02731fa58596f5e2e13cb368764e6d87 Mon Sep 17 00:00:00 2001 From: asLody Date: Tue, 31 Oct 2017 17:40:20 +0800 Subject: [PATCH 003/334] [native-update] : update HookZz. --- VirtualApp/lib/src/main/jni/HookZz/README.md | 6 +- .../src/platforms/arch-arm/reader-thumb.c | 28 +-- .../src/platforms/arch-arm/reader-thumb.h | 2 +- .../src/platforms/arch-arm/relocator-arm.c | 33 ++- .../src/platforms/arch-arm/relocator-thumb.c | 30 ++- .../src/platforms/arch-arm/writer-arm.c | 2 +- .../src/platforms/arch-arm/writer-thumb.c | 77 +----- .../platforms/arch-arm64/relocator-arm64.c | 222 +----------------- .../platforms/backend-arm/trampoline-arm.c | 56 +++-- .../lib/src/main/jni/HookZz/src/zzinfo.h | 12 +- 10 files changed, 129 insertions(+), 339 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/HookZz/README.md b/VirtualApp/lib/src/main/jni/HookZz/README.md index d051bc50e..8e48d5555 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/README.md +++ b/VirtualApp/lib/src/main/jni/HookZz/README.md @@ -6,6 +6,8 @@ ref to: [frida-gum](https://github.com/frida/frida-gum) and [minhook](https://gi **special thanks to [frida-gum](https://github.com/frida/frida-gum) perfect code and modular architecture, frida is aircraft carrier, HookZz is boat, but still with some tricks** +**thanks for @lauos with contributing android code** + # Features - **inlinehook without Jailbreak [new-90%]** @@ -22,7 +24,7 @@ ref to: [frida-gum](https://github.com/frida/frida-gum) and [minhook](https://gi - hook **address(a piece of code)** with `pre_call` and `half_call` -- (almost)only **one instruction** to hook(i.e. hook **short funciton, even only one instruction**) [arm64] +- (almost)only **one instruction** to hook(i.e. hook **short funciton, even only one instruction**) [arm/thumb/arm64] - runtime code patch, without codesign limit @@ -163,7 +165,7 @@ and check `build/android-armv7/*` #### `test_hook_printf.c` output for arm64-ios -test hook `printf` with `try_near_jump` option and `replace_call`, `pre_call`, `post_call` +test hook `printf` with `try_near_jump` option , and `ZzEnableDebugMode()` with `replace_call`, `pre_call`, `post_call`. ``` ZzThunkerBuildThunk: diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c index 622ea6ddc..b4c6458d8 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c @@ -81,55 +81,55 @@ zpointer zz_thumb_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer // ARM Manual // A5 ARM Instruction Set Encoding // A5.3 Load/store word and unsigned byte -THUMBInsnType GetTHUMBInsnType(zuint32 insn) { - // zuint32 insn = insn_ctx->insn; +THUMBInsnType GetTHUMBInsnType(zuint16 insn1, zuint16 insn2) { + // zuint32 insn1 = insn_ctx->insn1; zuint32 op, op1; - if (!insn_is_thumb2(insn) && insn_equal(insn, "01000100xxxxxxxx")) { + if (!insn_is_thumb2(insn1) && insn_equal(insn1, "01000100xxxxxxxx")) { return THUMB_INS_ADD_register_T2; } - if (!insn_is_thumb2(insn) && insn_equal(insn, "01001xxxxxxxxxxx")) { + if (!insn_is_thumb2(insn1) && insn_equal(insn1, "01001xxxxxxxxxxx")) { return THUMB_INS_LDR_literal_T1; } - if (insn_is_thumb2(insn) && insn_equal(insn, "11111000x1011111xxxxxxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11111000x1011111") && insn_equal(insn2, "xxxxxxxxxxxxxxxx")) { return THUMB_INS_LDR_literal_T2; } - if (!insn_is_thumb2(insn) && insn_equal(insn, "10100xxxxxxxxxxx")) { + if (!insn_is_thumb2(insn1) && insn_equal(insn1, "10100xxxxxxxxxxx")) { return THUMB_INS_ADR_T1; } - if (insn_is_thumb2(insn) && insn_equal(insn, "11110x10101011110xxxxxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110x1010101111") && insn_equal(insn2, "0xxxxxxxxxxxxxxx")) { return THUMB_INS_ADR_T2; } - if (insn_is_thumb2(insn) && insn_equal(insn, "11110x10000011110xxxxxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110x1000001111") && insn_equal(insn2, "0xxxxxxxxxxxxxxx")) { return THUMB_INS_ADR_T3; } - if (!insn_is_thumb2(insn) && insn_equal(insn, "1101xxxxxxxxxxxx")) { + if (!insn_is_thumb2(insn1) && insn_equal(insn1, "1101xxxxxxxxxxxx")) { return THUMB_INS_B_T1; } - if (!insn_is_thumb2(insn) && insn_equal(insn, "11100xxxxxxxxxxx")) { + if (!insn_is_thumb2(insn1) && insn_equal(insn1, "11100xxxxxxxxxxx")) { return THUMB_INS_B_T2; } - if (insn_is_thumb2(insn) && insn_equal(insn, "11110xxxxxxxxxxx10x0xxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110xxxxxxxxxxx") && insn_equal(insn2, "10x0xxxxxxxxxxxx")) { return THUMB_INS_B_T3; } - if (insn_is_thumb2(insn) && insn_equal(insn, "11110xxxxxxxxxxx10x0xxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110xxxxxxxxxxx") && insn_equal(insn2, "10x0xxxxxxxxxxxx")) { return THUMB_INS_B_T4; } - if (insn_is_thumb2(insn) && insn_equal(insn, "11110xxxxxxxxxxx11x1xxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110xxxxxxxxxxx") && insn_equal(insn2, "11x1xxxxxxxxxxxx")) { return THUMB_INS_BLBLX_immediate_T1; } - if (insn_is_thumb2(insn) && insn_equal(insn, "11110xxxxxxxxxxx11x0xxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110xxxxxxxxxxx") && insn_equal(insn2, "11x0xxxxxxxxxxxx")) { return THUMB_INS_BLBLX_immediate_T2; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h index 883bdb6d4..787ccb0c7 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h @@ -42,7 +42,7 @@ typedef enum _THUMBInsnType { THUMB_UNDEF } THUMBInsnType; -THUMBInsnType GetTHUMBInsnType(zuint32 insn); +THUMBInsnType GetTHUMBInsnType(zuint16 insn1, zuint16 insn2); zpointer zz_thumb_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer address); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c index 25d2fa83f..29108fe97 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c @@ -116,7 +116,7 @@ static zbool zz_arm_relocator_rewrite_LDR_literal_A1(ZzArmRelocator *self, const static zbool zz_arm_relocator_rewrite_ADR_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm12 = get_insn_sub(insn, 0, 12); - zuint32 imm32 = imm12 << 2; + zuint32 imm32 = imm12; zaddr target_address; target_address = insn_ctx->pc + imm32; int Rt_ndx = get_insn_sub(insn, 12, 4); @@ -128,7 +128,7 @@ static zbool zz_arm_relocator_rewrite_ADR_A1(ZzArmRelocator *self, const ZzInstr static zbool zz_arm_relocator_rewrite_ADR_A2(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm12 = get_insn_sub(insn, 0, 12); - zuint32 imm32 = imm12 << 2; + zuint32 imm32 = imm12; zaddr target_address; target_address = insn_ctx->pc - imm32; int Rt_ndx = get_insn_sub(insn, 12, 4); @@ -136,6 +136,12 @@ static zbool zz_arm_relocator_rewrite_ADR_A2(ZzArmRelocator *self, const ZzInstr return TRUE; } +// 0x000 : b.cond 0x0; +// 0x004 : b 0x4 +// 0x008 : ldr pc, [pc, #0] +// 0x00c : .long 0x0 +// 0x010 : remain code + // PAGE: A8-334 static zbool zz_arm_relocator_rewrite_B_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn = insn_ctx->insn; @@ -143,10 +149,26 @@ static zbool zz_arm_relocator_rewrite_B_A1(ZzArmRelocator *self, const ZzInstruc zuint32 imm32 = imm24 << 2; zaddr target_address; target_address = insn_ctx->pc + imm32; + + zz_arm_writer_put_instruction(self->output, (insn & 0xFF000000) | 0); + zz_arm_writer_put_b_imm(self->output, 0x4); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; } +// 0x000 : bl.cond 0x0; + +// 0x004 : b 0x10 + +// 0x008 : ldr lr, [pc, #0] +// 0x00c : b 0x0 +// 0x010 : .long 0x0 + +// 0x014 : ldr pc, [pc, #0] +// 0x018 : .long 0x0 + +// 0x01c : remain code + // PAGE: A8-348 static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn = insn_ctx->insn; @@ -154,7 +176,10 @@ static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A1(ZzArmRelocator *self, c zuint32 imm32 = imm24 << 2; zaddr target_address; target_address = insn_ctx->pc + imm32; - zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 2 * 4); + + zz_arm_writer_put_instruction(self->output, (insn & 0xFF000000) | 0); + zz_arm_writer_put_b_imm(self->output, 0x10); + zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 0xc); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; } @@ -167,7 +192,7 @@ static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A2(ZzArmRelocator *self, c zuint32 imm32 = (imm24 << 2) | (H << 1); zaddr target_address; target_address = insn_ctx->pc + imm32; - zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 2 * 4); + zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 0x8); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c index 30c8fbbb3..4871c86be 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c @@ -173,6 +173,12 @@ zbool zz_thumb_relocator_rewrite_ADR_T3(ZzThumbRelocator *self, const ZzInstruct return TRUE; } +// 0x000 : b.cond 0x0; +// 0x002 : b 0x6 +// 0x004 : ldr pc, [pc, #0] +// 0x008 : .long 0x0 +// 0x00c : remain code + // PAGE: A8-334 zbool zz_thumb_relocator_rewrite_B_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn1 = insn_ctx->insn1; @@ -182,7 +188,12 @@ zbool zz_thumb_relocator_rewrite_B_T1(ZzThumbRelocator *self, const ZzInstructio zuint32 imm32 = imm8 << 1; zaddr target_address = insn_ctx->pc + imm32; - zz_thumb_writer_put_instruction(self->output, (insn1 & 0xFF00)); + /* for align , simple solution, maybe the correct solution is get `ldr_reg_address` length and adjust the immediate + * of `b_imm`. */ + if ((zaddr)self->output->pc % 4) { + zz_thumb_writer_put_nop(self->output); + } + zz_thumb_writer_put_instruction(self->output, (insn1 & 0xFF00) | 0); zz_thumb_writer_put_b_imm(self->output, 0x6); zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; @@ -191,7 +202,6 @@ zbool zz_thumb_relocator_rewrite_B_T1(ZzThumbRelocator *self, const ZzInstructio // PAGE: A8-334 zbool zz_thumb_relocator_rewrite_B_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn1 = insn_ctx->insn1; - // zuint32 insn2 = insn_ctx->insn2; zuint32 imm11 = get_insn_sub(insn1, 0, 11); zuint32 imm32 = imm11 << 1; @@ -201,6 +211,12 @@ zbool zz_thumb_relocator_rewrite_B_T2(ZzThumbRelocator *self, const ZzInstructio return TRUE; } +// 0x002 : b.cond.W 0x2; +// 0x006 : b 0x6 +// 0x008 : ldr pc, [pc, #0] +// 0x00c : .long 0x0 +// 0x010 : remain code + // PAGE: A8-334 zbool zz_thumb_relocator_rewrite_B_T3(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn1 = insn_ctx->insn1; @@ -216,7 +232,13 @@ zbool zz_thumb_relocator_rewrite_B_T3(ZzThumbRelocator *self, const ZzInstructio zaddr target_address; target_address = insn_ctx->pc + imm32; - zz_thumb_writer_put_instruction(self->output, (insn_ctx->insn & 0b11010000000000001111101111000000) | 0b1); + /* for align , simple solution, maybe the correct solution is get `ldr_reg_address` length and adjust the immediate + * of `b_imm`. */ + if ((zaddr)self->output->pc % 4 == 0) { + zz_thumb_writer_put_nop(self->output); + } + zz_thumb_writer_put_instruction(self->output, insn_ctx->insn1 & 0b1111101111000000); + zz_thumb_writer_put_instruction(self->output, (insn_ctx->insn2 & 0b1101000000000000) | 0b1); zz_thumb_writer_put_b_imm(self->output, 0x6); zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; @@ -297,7 +319,7 @@ zbool zz_thumb_relocator_write_one(ZzThumbRelocator *self) { } else return FALSE; - switch (GetTHUMBInsnType(insn_ctx->insn)) { + switch (GetTHUMBInsnType(insn_ctx->insn1, insn_ctx->insn2)) { case THUMB_INS_ADD_register_T2: rewritten = zz_thumb_relocator_rewrite_ADD_register_T2(self, insn_ctx); break; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c index f1bbb59d0..0911f2c32 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c @@ -20,7 +20,7 @@ // ATTENTION !!!: // 写 writer 部分, 需要参考, `Instrcution Set Encoding` 部分 -// `witer` REF: `ZzInstruction Set Encoding` +// `writer` REF: `ZzInstruction Set Encoding` ZzArmWriter *zz_arm_writer_new(zpointer data_ptr) { ZzArmWriter *writer = (ZzArmWriter *)malloc(sizeof(ZzArmWriter)); diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c index a39a96c4f..8a5654275 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c @@ -48,23 +48,8 @@ zsize zz_thumb_writer_near_jump_range_size() { return ((1 << 23) << 1); } zpointer zz_thumb_writer_put_ldr_b_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address) { ZzArmRegInfo ri; - zz_arm_register_describe(reg, &ri); - // if (((zaddr)self->pc) % 4) { - // zz_thumb_writer_put_ldr_reg_imm(self, reg, 0x4); - // if (ri.meta <= ZZ_ARM_REG_R7) { - // zz_thumb_writer_put_nop(self); - // } - // } else { - // if (ri.meta <= ZZ_ARM_REG_R7) { - // zz_thumb_writer_put_ldr_reg_imm(self, reg, 0x0); - // } else { - // zz_thumb_writer_put_ldr_reg_imm(self, reg, 0x4); - // zz_thumb_writer_put_nop(self); - // } - // } - if ((((zaddr)self->pc) % 4)) { if (ri.meta <= ZZ_ARM_REG_R7) { zz_thumb_writer_put_ldr_reg_imm(self, reg, 0x4); @@ -88,8 +73,8 @@ zpointer zz_thumb_writer_put_ldr_b_reg_address(ZzThumbWriter *self, ZzARMReg reg zpointer zz_thumb_writer_put_ldr_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address) { ZzArmRegInfo ri; - zz_arm_register_describe(reg, &ri); + if ((((zaddr)self->pc) % 4)) { if (ri.meta <= ZZ_ARM_REG_R7) { zz_thumb_writer_put_ldr_reg_imm(self, reg, 0x0); @@ -103,9 +88,6 @@ zpointer zz_thumb_writer_put_ldr_reg_address(ZzThumbWriter *self, ZzARMReg reg, zz_thumb_writer_put_nop(self); } - // if ((((zaddr)self->pc) % 4)) { - // zz_thumb_writer_put_nop(self); - // } zz_thumb_writer_put_bytes(self, (zpointer)&address, sizeof(zpointer)); return self->pc; } @@ -219,60 +201,6 @@ zpointer zz_thumb_writer_put_ldr_reg_imm(ZzThumbWriter *self, ZzARMReg reg, zint return self->pc; } -// static zpointer zz_thumb_writer_put_transfer_reg_reg_offset(ZzThumbWriter -// *self, -// ZzThumbMemoryOperation -// operation, -// ZzARMReg left_reg, -// ZzARMReg right_reg, -// zint32 right_offset) -// { -// zz_arm_register_describe(left_reg, &lr); -// zz_arm_register_describe(right_reg, &rr); - -// if (right_offset >= 0) { -// if (lr.meta <= ZZ_ARM_REG_R7 && (rr.meta <= ZZ_ARM_REG_R7 || rr.meta == -// ZZ_ARM_REG_SP) && -// ((rr.meta == ZZ_ARM_REG_SP && right_offset <= 1020) || -// (rr.meta != ZZ_ARM_REG_SP && right_offset <= 124)) && -// (right_offset % 4) == 0) { -// zuint16 insn; - -// if (rr.meta == ZZ_ARM_REG_SP) -// insn = 0x9000 | (lr.index << 8) | (right_offset / 4); -// else -// insn = 0x6000 | (right_offset / 4) << 6 | (rr.index << 3) | -// lr.index; - -// if (operation == ZZ_THUMB_MEMORY_LOAD) -// insn |= 0x0800; - -// zz_thumb_writer_put_instruction(self, insn); -// } else { -// if (right_offset > 4095) -// return; -// zz_thumb_writer_put_instruction( -// self, 0xf8c0 | ((operation == ZZ_THUMB_MEMORY_LOAD) ? 0x0010 -// : 0x0000) | -// rr.index); -// zz_thumb_writer_put_instruction(self, (lr.index << 12) | -// right_offset); -// } -// } else { -// if ((rr.index & 0xF) == 0xF) { -// zz_thumb_writer_put_ldr_reg_imm(self, left_reg, right_offset); -// } else { -// zz_thumb_writer_put_instruction( -// self, 0xf840 | ((operation == ZZ_THUMB_MEMORY_LOAD) ? 0x0010 -// : 0x0000) | -// rr.index); -// zz_thumb_writer_put_instruction(self, 0x0c00 | (lr.index << 12) | -// (ABS(right_offset) & -// ZZ_INT8_MASK)); -// } -// } -// } - zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T1(ZzThumbWriter *self, ZzThumbMemoryOperation operation, ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { ZzArmRegInfo lr, rr; @@ -507,6 +435,7 @@ zpointer zz_thumb_writer_put_push_reg(ZzThumbWriter *self, zint32 regs) { register_list = regs & 0xFF; zz_thumb_writer_put_instruction(self, 0b1011010000000000 | M << 8 | register_list); + return self->pc; } zpointer zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs) { @@ -515,6 +444,7 @@ zpointer zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs) { register_list = regs & 0xFF; zz_thumb_writer_put_instruction(self, 0b1011110000000000 | P << 8 | register_list); + return self->pc; } zpointer zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, @@ -530,4 +460,5 @@ zpointer zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_r Rn_ndx = left.index; zz_thumb_writer_put_instruction(self, 0b0001100000000000 | Rm_ndx << 6 | Rn_ndx << 3 | Rd_ndx); + return self->pc; } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c index ab97f45ce..eb4a49a6f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c @@ -45,50 +45,6 @@ void zz_arm64_relocator_reset(ZzArm64Relocator *self, zpointer input_code, ZzArm self->output = output; } -// zsize zz_arm64_relocator_read_one(ZzArm64Relocator *self, ZzInstruction *instruction) { -// insn_cs **insn_ctx_ptr, *insn_cs; -// ZzInstruction insn_ctx = self->input_insns[self->inpos]; -// insn_ctx_ptr = &insn_ctx.insn_cs; - -// if (cs_disasm(self->capstone, self->input_cur, 4, self->input_pc, 1, insn_ctx_ptr) != 1) { -// return 0; -// } - -// insn_cs = *insn_ctx_ptr; - -// // zbool flag = TRUE; -// // switch (insn_cs->id) { -// // case ARM64_INS_B: -// // if (branch_is_unconditional(ins)) -// // flag = relocator_rewrite_b(ins, relocate_writer); -// // else -// // flag = relocator_rewrite_b_cond(ins, relocate_writer); -// // break; -// // case ARM64_INS_LDR: -// // flag = relocator_rewrite_ldr(ins, relocate_writer); -// // break; -// // case ARM64_INS_ADR: -// // case ARM64_INS_ADRP: -// // flag = relocator_rewrite_adr(ins, relocate_writer); -// // break; -// // case ARM64_INS_BL: -// // flag = relocator_rewrite_bl(ins, relocate_writer); -// // break; -// // default: -// // zz_arm64_writer_put_bytes(relocate_writer, address, insn_cs->size); -// // } -// // if (!flag) -// // zz_arm64_writer_put_bytes(relocate_writer, address, insn_cs->size); - -// if (instruction != NULL) -// *instruction = insn_ctx; - -// self->input_cur += insn_cs->size; -// self->input_pc += insn_cs->size; - -// return self->input_cur - self->input_start; -// } - zsize zz_arm64_relocator_read_one(ZzArm64Relocator *self, ZzInstruction *instruction) { ZzInstruction *insn_ctx = &self->input_insns[self->inpos]; @@ -118,161 +74,6 @@ void zz_arm64_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *m return; } -// static zbool zz_arm64_branch_is_unconditional(const cs_insn *insn) { -// switch (insn->detail->arm64.cc) { -// case ARM64_CC_INVALID: -// case ARM64_CC_AL: -// case ARM64_CC_NV: -// return TRUE; -// default: -// return FALSE; -// } -// } - -// static zbool zz_arm64_relocator_rewrite_ldr(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { -// const cs_arm64_op *dst = &insn_ctx->detail->operands[0]; -// const cs_arm64_op *src = &insn_ctx->detail->operands[1]; -// zbool dst_reg_is_fp_or_simd; -// ZzARM64Reg tmp_reg; - -// (void)self; - -// if (src->type != ARM64_OP_IMM) -// return FALSE; - -// dst_reg_is_fp_or_simd = (dst->reg >= ARM64_REG_S0 && dst->reg <= ARM64_REG_S31) || -// (dst->reg >= ARM64_REG_D0 && dst->reg <= ARM64_REG_D31) || -// (dst->reg >= ARM64_REG_Q0 && dst->reg <= ARM64_REG_Q31); -// if (dst_reg_is_fp_or_simd) { -// #if defined(DEBUG_MODE) -// debug_break(); -// #endif -// } else { -// if (dst->reg >= ARM64_REG_W0 && dst->reg <= ARM64_REG_W28) -// tmp_reg = ZZ_ARM64_REG_X0 + (dst->reg - ARM64_REG_W0); -// else if (dst->reg >= ARM64_REG_W29 && dst->reg <= ARM64_REG_W30) -// tmp_reg = ZZ_ARM64_REG_X29 + (dst->reg - ARM64_REG_W29); -// else -// tmp_reg = dst->reg; - -// zz_arm64_writer_put_ldr_b_reg_address(self->output, tmp_reg, src->imm); -// zz_arm64_writer_put_ldr_reg_reg_offset(self->output, dst->reg, tmp_reg, 0); -// } - -// return TRUE; -// } - -// static zbool zz_arm64_relocator_rewrite_adr(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { -// const cs_arm64_op *dst = &insn_ctx->detail->operands[0]; -// const cs_arm64_op *label = &insn_ctx->detail->operands[1]; - -// zz_arm64_writer_put_ldr_b_reg_address(self->output, dst->reg, label->imm); -// return TRUE; -// } - -// static zbool zz_arm64_relocator_rewrite_b(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { -// const cs_arm64_op *target = &insn_ctx->detail->operands[0]; - -// zz_arm64_writer_put_ldr_b_reg_address(self->output, ZZ_ARM64_REG_X17, target->imm); - -// return TRUE; -// } - -// static zbool zz_arm64_relocator_rewrite_b_cond(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { -// const cs_arm64_op *target = &insn_ctx->detail->operands[0]; - -// zz_arm64_writer_put_b_cond_imm(self->output, insn_ctx->detail->cc, 0x8); -// zz_arm64_writer_put_b_imm(self->output, 0x4 + 0x14); - -// zz_arm64_writer_put_ldr_br_reg_address(self->output, ZZ_ARM64_REG_X17, target->imm); - -// return TRUE; -// } - -// static zbool zz_arm64_relocator_rewrite_bl(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { -// const cs_arm64_op *target = &insn_ctx->detail->operands[0]; - -// zz_arm64_writer_put_ldr_br_reg_address(self->output, ZZ_ARM64_REG_LR, target->imm); - -// return TRUE; -// } - -// zbool relocator_rewrite_ldr(ZzInstruction *ins, ZzArm64Writer *relocate_writer) -// { -// cs_arm64 ins_csd = ins->insn_cs->detail->arm64; -// const cs_arm64_op *dst = &ins_csd.operands[0]; -// const cs_arm64_op *src = &ins_csd.operands[1]; -// if (src->type != ARM64_OP_IMM) -// return FALSE; -// return TRUE; -// } - -// zbool relocator_rewrite_b(ZzInstruction *ins, ZzArm64Writer *relocate_writer) { -// cs_arm64 ins_csd = ins->insn_cs->detail->arm64; -// zaddr target_addr = ins_csd.operands[0].imm; - -// // zz_arm64_writer_put_ldr_br_b_reg_address(relocate_writer, -// ZZ_ARM64_REG_X17, -// // target_addr); -// zz_arm64_writer_put_ldr_reg_address(relocate_writer, ZZ_ARM64_REG_X17, -// target_addr); -// zz_arm64_writer_put_br_reg(relocate_writer, ZZ_ARM64_REG_X17); -// return TRUE; -// } - -// zbool relocator_rewrite_bl(ZzInstruction *ins, ZzArm64Writer *relocate_writer) -// { -// cs_arm64 ins_csd = ins->insn_cs->detail->arm64; -// zaddr target_addr = ins_csd.operands[0].imm; - -// zz_arm64_writer_put_ldr_reg_address(relocate_writer, ZZ_ARM64_REG_X17, -// target_addr); -// zz_arm64_writer_put_blr_reg(relocate_writer, ZZ_ARM64_REG_X17); -// return TRUE; -// } - -// /* -// origin: -// 1. j.eq [3] - -// 2. [...] -// 3. [...] - -// rwrite: -// 1. j.eq [1.2] -// 1.1 b [2] -// 1.2 abs_jmp [3] - -// 2. [...] -// 3. [...] -// */ -// zbool relocator_rewrite_b_cond(ZzInstruction *ins, -// ZzArm64Writer *relocate_writer) { -// cs_arm64 ins_csd = ins->insn_cs->detail->arm64; -// zaddr target_addr = ins_csd.operands[0].imm; - -// zz_arm64_writer_put_b_cond_imm(relocate_writer, ins_csd.cc, 0x8); -// zz_arm64_writer_put_b_imm(relocate_writer, 0x4 + 0x14); - -// // zz_arm64_writer_put_ldr_br_b_reg_address(relocate_writer, -// ZZ_ARM64_REG_X17, -// // target_addr); -// zz_arm64_writer_put_ldr_reg_address(relocate_writer, ZZ_ARM64_REG_X17, -// target_addr); -// zz_arm64_writer_put_br_reg(relocate_writer, ZZ_ARM64_REG_X17); -// return TRUE; -// } - -// zbool relocator_rewrite_adr(ZzInstruction *ins, ZzArm64Writer *relocate_writer) -// { -// cs_arm64 ins_csd = ins->insn_cs->detail->arm64; - -// const cs_arm64_op dst = ins_csd.operands[0]; -// const cs_arm64_op label = ins_csd.operands[1]; -// zz_arm64_writer_put_ldr_reg_address(relocate_writer, dst.reg, label.imm); -// return TRUE; -// } - // PAGE: C6-673 static zbool zz_arm64_relocator_rewrite_LDR_literal(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { zuint32 insn = insn_ctx->insn; @@ -313,7 +114,7 @@ static zbool zz_arm64_relocator_rewrite_ADRP(ZzArm64Relocator *self, const ZzIns zuint64 imm = immhi << 2 << 12 | immlo << 12; zaddr target_address; - target_address = (insn_ctx->pc & (1 << 12)) + imm; + target_address = (insn_ctx->pc & 0xFFFFFFFFFFFFF000) + imm; int Rt_ndx = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); @@ -350,21 +151,16 @@ static zbool zz_arm64_relocator_rewrite_BL(ZzArm64Relocator *self, const ZzInstr return TRUE; } -/* - origin: - 1. j.eq [3] +// 0x000 : b.cond 0x8; - 2. [...] - 3. [...] +// 0x004 : b 0x14 - rwrite: - 1. j.eq [1.2] - 1.1 b [2] - 1.2 abs_jmp [3] +// 0x008 : ldr x17, [pc, #4] +// 0x00c : br x17 +// 0x010 : .long 0x0 +// 0x014 : .long 0x0 - 2. [...] - 3. [...] - */ +// 0x018 : remain code // PAGE: C6-549 static zbool zz_arm64_relocator_rewrite_B_cond(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { @@ -379,7 +175,7 @@ static zbool zz_arm64_relocator_rewrite_B_cond(ZzArm64Relocator *self, const ZzI zuint32 cond = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_b_cond_imm(self->output, cond, 0x8); - zz_arm64_writer_put_b_imm(self->output, 0xc); + zz_arm64_writer_put_b_imm(self->output, 0x14); zz_arm64_writer_put_ldr_br_reg_address(self->output, ZZ_ARM64_REG_X17, target_address); return TRUE; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c index 33423c526..0df688749 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c @@ -45,14 +45,16 @@ ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbool is_thumb = FALSE; - zpointer target_addr = entry->target_ptr; + zpointer target_addr; zuint redirect_limit; ZzArmHookFunctionEntryBackend *entry_backend; entry_backend = (ZzArmHookFunctionEntryBackend *)malloc(sizeof(ZzArmHookFunctionEntryBackend)); entry->backend = (struct _ZzHookFunctionEntryBackend *)entry_backend; - is_thumb = INSTRUCTION_IS_THUMB((zaddr)target_addr); + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); if (is_thumb) { if (entry->try_near_jump) { @@ -60,6 +62,9 @@ ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *en } else { zz_thumb_relocator_try_relocate(target_addr, ZZ_THUMB_FULL_REDIRECT_SIZE, &redirect_limit); entry_backend->redirect_code_size = ZZ_THUMB_FULL_REDIRECT_SIZE; + if ((zaddr)target_addr % 4) { + entry_backend->redirect_code_size += 2; + } } } else { if (entry->try_near_jump) { @@ -83,9 +88,12 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; + zpointer target_addr; + + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - is_thumb = INSTRUCTION_IS_THUMB((zaddr)target_addr); if (is_thumb) { thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); @@ -98,8 +106,8 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti return ZZ_FAILED; break; } - code_slice = ZzNewNearCodeSlice(self->allocator, (zaddr)entry->target_ptr, - zz_thumb_writer_near_jump_range_size(), thumb_writer->size); + code_slice = ZzNewNearCodeSlice(self->allocator, (zaddr)target_addr, zz_thumb_writer_near_jump_range_size(), + thumb_writer->size); if (!code_slice) { return ZZ_FAILED; } else { @@ -121,8 +129,8 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti return ZZ_FAILED; break; } - code_slice = ZzNewNearCodeSlice(self->allocator, (zaddr)entry->target_ptr, - zz_arm_writer_near_jump_range_size(), arm_writer->size); + code_slice = ZzNewNearCodeSlice(self->allocator, (zaddr)target_addr, zz_arm_writer_near_jump_range_size(), + arm_writer->size); if (!code_slice) { return ZZ_FAILED; } else { @@ -153,12 +161,14 @@ ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; + zpointer target_addr; thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - is_thumb = INSTRUCTION_IS_THUMB((zaddr)target_addr); + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); code_slice = NULL; do { @@ -220,14 +230,15 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; + zpointer target_addr; zpointer target_end_addr = 0; zpointer restore_target_addr; - is_thumb = INSTRUCTION_IS_THUMB((zaddr)target_addr); + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); if (is_thumb) { - target_addr = (zpointer)((zaddr)target_addr & ~(zaddr)1); target_end_addr = (zpointer)((zaddr)entry->target_end_ptr & ~(zaddr)1); } @@ -405,12 +416,14 @@ ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry * ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; + zpointer target_addr; thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - is_thumb = INSTRUCTION_IS_THUMB((zaddr)target_addr); + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); code_slice = NULL; do { @@ -461,11 +474,13 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - zpointer target_addr = entry->target_ptr; + zpointer target_addr; thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - is_thumb = INSTRUCTION_IS_THUMB((zaddr)target_addr); + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); code_slice = NULL; do { @@ -522,12 +537,13 @@ ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *e ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; + zpointer target_addr; - is_thumb = INSTRUCTION_IS_THUMB((zaddr)target_addr); + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); if (is_thumb) { - target_addr = (zpointer)((zaddr)target_addr & ~(zaddr)1); ZzThumbWriter *thumb_writer; thumb_writer = &self->thumb_writer; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/zzinfo.h b/VirtualApp/lib/src/main/jni/HookZz/src/zzinfo.h index 2b8a883d8..db9d37f17 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/zzinfo.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/zzinfo.h @@ -27,20 +27,18 @@ typedef struct _ZzInfo { zbool g_enable_debug_flag; -// LOGFUNC g_log_func; } ZzInfo; ZzInfo *ZzInfoObtain(void); zbool ZzIsEnableDebugMode(); -#if TARGET_OS_IPHONE -#include -void NSLog(CFStringRef format, ...); -#define ZzInfoLog(fmt, ...) \ - { NSLog(CFSTR(fmt), ##__VA_ARGS__); } -#elif defined(__ANDROID__) +#if defined(__ANDROID__) #include #define ZzInfoLog(fmt, ...) \ { __android_log_print(ANDROID_LOG_INFO, "zzinfo", fmt, __VA_ARGS__); } +#else +#define ZzInfoLog(fmt, ...) \ + { Xinfo(fmt, __VA_ARGS__); } #endif + #endif \ No newline at end of file From 54621ef4f0302805ab188faa92785716995de7fe Mon Sep 17 00:00:00 2001 From: asLody Date: Tue, 31 Oct 2017 21:03:39 +0800 Subject: [PATCH 004/334] [native-update] : update HookZz. --- .../HookZz/src/platforms/arch-arm/relocator-arm.c | 2 +- .../src/platforms/backend-arm/trampoline-arm.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c index 29108fe97..0a0c1fe40 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c @@ -98,7 +98,7 @@ static zbool zz_arm_relocator_rewrite_ADD_register_A1(ZzArmRelocator *self, cons static zbool zz_arm_relocator_rewrite_LDR_literal_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm12 = get_insn_sub(insn, 0, 12); - zuint32 imm32 = imm12 << 2; + zuint32 imm32 = imm12; zbool add = get_insn_sub(insn, 7 + 16, 1) == 1; zaddr target_address; if (add) diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c index 0df688749..feadf7a1c 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c @@ -45,7 +45,7 @@ ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbool is_thumb = FALSE; - zpointer target_addr; + zpointer target_addr = entry->target_ptr; zuint redirect_limit; ZzArmHookFunctionEntryBackend *entry_backend; @@ -88,7 +88,7 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr; + zpointer target_addr = entry->target_ptr; is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); if (is_thumb) @@ -161,7 +161,7 @@ ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr; + zpointer target_addr = entry->target_ptr; thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); @@ -230,7 +230,7 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr; + zpointer target_addr = entry->target_ptr; zpointer target_end_addr = 0; zpointer restore_target_addr; @@ -416,7 +416,7 @@ ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry * ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr; + zpointer target_addr = entry->target_ptr; thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); @@ -474,7 +474,7 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - zpointer target_addr; + zpointer target_addr = entry->target_ptr; thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); @@ -537,7 +537,7 @@ ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *e ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; zbool is_thumb = TRUE; - zpointer target_addr; + zpointer target_addr = entry->target_ptr; is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); if (is_thumb) From a3c26ec200d6f18840028fb9717ee7c53f1638ee Mon Sep 17 00:00:00 2001 From: asLody Date: Tue, 31 Oct 2017 21:45:33 +0800 Subject: [PATCH 005/334] [native-jni] : optimize the jni code. --- VirtualApp/lib/src/main/jni/Jni/Helper.h | 22 ++++++- VirtualApp/lib/src/main/jni/Jni/VAJni.cpp | 71 +++++++++++------------ 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Jni/Helper.h b/VirtualApp/lib/src/main/jni/Jni/Helper.h index 727e10a71..398fd7b91 100644 --- a/VirtualApp/lib/src/main/jni/Jni/Helper.h +++ b/VirtualApp/lib/src/main/jni/Jni/Helper.h @@ -5,9 +5,27 @@ #ifndef NDK_LOG_H #define NDK_LOG_H - -#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) +#include #define NATIVE_METHOD(func_ptr, func_name, signature) { func_name, signature, reinterpret_cast(func_ptr) } +class ScopeUtfString { +public: + ScopeUtfString(jstring j_str) : _j_str(j_str), + _c_str(facebook::jni::Environment::current()->GetStringUTFChars(j_str, NULL)) { + } + + const char *c_str() { + return _c_str; + } + + ~ScopeUtfString() { + facebook::jni::Environment::current()->ReleaseStringUTFChars(_j_str, _c_str); + } + +private: + jstring _j_str; + const char *_c_str; +}; + #endif //NDK_LOG_H diff --git a/VirtualApp/lib/src/main/jni/Jni/VAJni.cpp b/VirtualApp/lib/src/main/jni/Jni/VAJni.cpp index 4bde8bd76..aa0db1170 100644 --- a/VirtualApp/lib/src/main/jni/Jni/VAJni.cpp +++ b/VirtualApp/lib/src/main/jni/Jni/VAJni.cpp @@ -10,61 +10,48 @@ using namespace facebook::jni; static void jni_nativeLaunchEngine(alias_ref clazz, JArrayClass javaMethods, - jstring packageName, - jboolean isArt, jint apiLevel, jint cameraMethodType) { + jstring packageName, + jboolean isArt, jint apiLevel, jint cameraMethodType) { hookAndroidVM(javaMethods, packageName, isArt, apiLevel, cameraMethodType); } static void jni_nativeEnableIORedirect(alias_ref, jstring selfSoPath, jint apiLevel, - jint preview_api_level) { - JNIEnv *env = Environment::current(); - const char *so_path = env->GetStringUTFChars(selfSoPath, NULL); - IOUniformer::startUniformer(so_path, apiLevel, preview_api_level); - env->ReleaseStringUTFChars(selfSoPath, so_path); + jint preview_api_level) { + ScopeUtfString so_path(selfSoPath); + IOUniformer::startUniformer(so_path.c_str(), apiLevel, preview_api_level); } static void jni_nativeIOWhitelist(alias_ref jclazz, jstring _path) { - JNIEnv *env = Environment::current(); - const char *path = Environment::current()->GetStringUTFChars(_path, NULL); - IOUniformer::whitelist(path); - env->ReleaseStringUTFChars(_path, path); + ScopeUtfString path(_path); + IOUniformer::whitelist(path.c_str()); } static void jni_nativeIOForbid(alias_ref jclazz, jstring _path) { - JNIEnv *env = Environment::current(); - const char *path = env->GetStringUTFChars(_path, NULL); - IOUniformer::forbid(path); - env->ReleaseStringUTFChars(_path, path); + ScopeUtfString path(_path); + IOUniformer::forbid(path.c_str()); } static void jni_nativeIORedirect(alias_ref jclazz, jstring origPath, jstring newPath) { - JNIEnv *env = Environment::current(); - const char *orig_path = env->GetStringUTFChars(origPath, NULL); - const char *new_path = env->GetStringUTFChars(newPath, NULL); - IOUniformer::redirect(orig_path, new_path); - env->ReleaseStringUTFChars(origPath, orig_path); - env->ReleaseStringUTFChars(newPath, new_path); + ScopeUtfString orig_path(origPath); + ScopeUtfString new_path(newPath); + IOUniformer::redirect(orig_path.c_str(), new_path.c_str()); } static jstring jni_nativeGetRedirectedPath(alias_ref jclazz, jstring origPath) { - JNIEnv *env = Environment::current(); - const char *orig_path = env->GetStringUTFChars(origPath, NULL); - const char *redirected_path = IOUniformer::query(orig_path); - env->ReleaseStringUTFChars(origPath, orig_path); + ScopeUtfString orig_path(origPath); + const char *redirected_path = IOUniformer::query(orig_path.c_str()); if (redirected_path != NULL) { - return env->NewStringUTF(redirected_path); + return Environment::current()->NewStringUTF(redirected_path); } return NULL; } static jstring jni_nativeReverseRedirectedPath(alias_ref jclazz, jstring redirectedPath) { - JNIEnv *env = Environment::current(); - const char *redirected_path = env->GetStringUTFChars(redirectedPath, NULL); - const char *orig_path = IOUniformer::reverse(redirected_path); - env->ReleaseStringUTFChars(redirectedPath, redirected_path); + ScopeUtfString redirected_path(redirectedPath); + const char *orig_path = IOUniformer::reverse(redirected_path.c_str()); return Environment::current()->NewStringUTF(orig_path); } @@ -76,14 +63,22 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { return initialize(vm, [] { nativeEngineClass = findClassStatic("com/lody/virtual/client/NativeEngine"); nativeEngineClass->registerNatives({ - makeNativeMethod("nativeEnableIORedirect", jni_nativeEnableIORedirect), - makeNativeMethod("nativeIOWhitelist", jni_nativeIOWhitelist), - makeNativeMethod("nativeIOForbid", jni_nativeIOForbid), - makeNativeMethod("nativeIORedirect", jni_nativeIORedirect), - makeNativeMethod("nativeGetRedirectedPath", jni_nativeGetRedirectedPath), - makeNativeMethod("nativeReverseRedirectedPath", jni_nativeReverseRedirectedPath), - makeNativeMethod("nativeLaunchEngine", jni_nativeLaunchEngine), - }); + makeNativeMethod("nativeEnableIORedirect", + jni_nativeEnableIORedirect), + makeNativeMethod("nativeIOWhitelist", + jni_nativeIOWhitelist), + makeNativeMethod("nativeIOForbid", + jni_nativeIOForbid), + makeNativeMethod("nativeIORedirect", + jni_nativeIORedirect), + makeNativeMethod("nativeGetRedirectedPath", + jni_nativeGetRedirectedPath), + makeNativeMethod("nativeReverseRedirectedPath", + jni_nativeReverseRedirectedPath), + makeNativeMethod("nativeLaunchEngine", + jni_nativeLaunchEngine), + } + ); }); } From e25aaf3a1fad665153e2b1cacdb3b1373c861253 Mon Sep 17 00:00:00 2001 From: asLody Date: Wed, 1 Nov 2017 11:07:47 +0800 Subject: [PATCH 006/334] [native-code] : update HookZz library. --- .../src/platforms/arch-arm/reader-arm.c | 47 ++---------- .../src/platforms/arch-arm/reader-thumb.c | 31 +------- .../src/platforms/arch-arm/relocator-arm.c | 76 ++----------------- .../src/platforms/arch-arm/relocator-thumb.c | 26 ++++--- .../src/platforms/arch-arm/writer-arm.c | 17 ++--- .../src/platforms/arch-arm/writer-arm.h | 4 +- 6 files changed, 39 insertions(+), 162 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c index 834191b59..a7cdf2807 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c @@ -16,35 +16,6 @@ #include "reader-arm.h" -// static csh handle; - -// void zz_arm_reader_capstone_init(void) { -// cs_err err = 0; - -// err = cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle); -// if (err) { -// Xerror("Failed on cs_open() with error returned: %u\n", err); -// exit(-1); -// } - -// cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); -// } - -// cs_insn *zz_arm_reader_disassemble_at(zpointer address) { -// if (!handle) -// zz_arm_reader_capstone_init(); -// cs_insn *insn; -// size_t count; -// count = cs_disasm(handle, address, 16, (unsigned long)address, 0, &insn); -// if (!insn) { -// #if defined(DEBUG_MODE) -// debug_break(); -// #endif -// Xerror("zz_arm_reader_disassemble_at error at %p", (zpointer)address); -// } -// return insn; -// } - zpointer zz_arm_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer address) { // ZzInstruction *insn = (ZzInstruction *)malloc(sizeof(ZzInstruction)); @@ -60,34 +31,30 @@ zpointer zz_arm_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer ad // A5 ARM Instruction Set Encoding // A5.3 Load/store word and unsigned byte ARMInsnType GetARMInsnType(zuint32 insn) { - zuint32 op, op1; - op1 = get_insn_sub(insn, 20, 5); - if (insn_equal(insn, "xxxx0000100xxxxxxxxxxxxxxxx0xxxx")) { + if (insn_equal(insn, "xxxx0000100xxxxxxxxxxxxxxxx0xxxx") && (get_insn_sub(insn, 28, 4) != 0xF)) { return ARM_INS_ADD_register_A1; } - if (insn_equal(insn, "xxxx0101x0011111xxxxxxxxxxxxxxxx")) { + if (insn_equal(insn, "xxxx0101x0011111xxxxxxxxxxxxxxxx") && (get_insn_sub(insn, 28, 4) != 0xF)) { return ARM_INS_LDR_literal_A1; } - if (insn_equal(insn, "xxxx001010001111xxxxxxxxxxxxxxxx")) { + if (insn_equal(insn, "xxxx001010001111xxxxxxxxxxxxxxxx") && (get_insn_sub(insn, 28, 4) != 0xF)) { return ARM_INS_ADR_A1; } - - if (insn_equal(insn, "xxxx001001001111xxxxxxxxxxxxxxxx")) { + if (insn_equal(insn, "xxxx001001001111xxxxxxxxxxxxxxxx") && (get_insn_sub(insn, 28, 4) != 0xF)) { return ARM_INS_ADR_A2; } - - if (insn_equal(insn, "xxxx1010xxxxxxxxxxxxxxxxxxxxxxxx")) { + if (insn_equal(insn, "xxxx1010xxxxxxxxxxxxxxxxxxxxxxxx") && (get_insn_sub(insn, 28, 4) != 0xF)) { return ARM_INS_B_A1; } - - if (insn_equal(insn, "xxxx1011xxxxxxxxxxxxxxxxxxxxxxxx")) { + if (insn_equal(insn, "xxxx1011xxxxxxxxxxxxxxxxxxxxxxxx") && (get_insn_sub(insn, 28, 4) != 0xF)) { return ARM_INS_BLBLX_immediate_A1; } if (insn_equal(insn, "1111101xxxxxxxxxxxxxxxxxxxxxxxxx")) { return ARM_INS_BLBLX_immediate_A2; } + return ARM_UNDEF; } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c index b4c6458d8..9f9f2819a 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c @@ -16,35 +16,6 @@ #include "reader-thumb.h" -// static csh handle; - -// void zz_thumb_reader_capstone_init(void) { -// cs_err err = 0; - -// err = cs_open(CS_ARCH_ARM, CS_MODE_THUMB, &handle); -// if (err) { -// Xerror("Failed on cs_open() with error returned: %u\n", err); -// exit(-1); -// } - -// cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); -// } - -// cs_insn *zz_thumb_reader_disassemble_at(zpointer address) { -// if (!handle) -// zz_thumb_reader_capstone_init(); -// cs_insn *insn; -// size_t count; -// count = cs_disasm(handle, address, 16, (unsigned long)address, 0, &insn); -// if (!insn) { -// #if defined(DEBUG_MODE) -// debug_break(); -// #endif -// Xerror("zz_thumb_reader_disassemble_at error at %p", (zpointer)address); -// } -// return insn; -// } - zbool insn_is_thumb2(zuint32 insn) { // PAGE: A6-221 // PAGE: A6-230 @@ -121,7 +92,7 @@ THUMBInsnType GetTHUMBInsnType(zuint16 insn1, zuint16 insn2) { return THUMB_INS_B_T3; } - if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110xxxxxxxxxxx") && insn_equal(insn2, "10x0xxxxxxxxxxxx")) { + if (insn_is_thumb2(insn1) && insn_equal(insn1, "11110xxxxxxxxxxx") && insn_equal(insn2, "10x1xxxxxxxxxxxx")) { return THUMB_INS_B_T4; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c index 0a0c1fe40..a274ccffd 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c @@ -86,11 +86,11 @@ static zbool zz_arm_relocator_rewrite_ADD_register_A1(ZzArmRelocator *self, cons return FALSE; } // push R7 - zz_arm_writer_put_push_reg(self->output, 1 << 7); + zz_arm_writer_put_push_reg(self->output, ZZ_ARM_REG_R7); zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_R7, insn_ctx->pc); - zz_arm_writer_put_instruction(self->output, (insn & 0xFFFF0FFF) | ZZ_ARM_REG_R7 << 16); + zz_arm_writer_put_instruction(self->output, (insn & 0xFFF0FFFF) | ZZ_ARM_REG_R7 << 16); // pop R7 - zz_arm_writer_put_pop_reg(self->output, 1 << 7); + zz_arm_writer_put_pop_reg(self->output, ZZ_ARM_REG_R7); return TRUE; } @@ -179,7 +179,7 @@ static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A1(ZzArmRelocator *self, c zz_arm_writer_put_instruction(self->output, (insn & 0xFF000000) | 0); zz_arm_writer_put_b_imm(self->output, 0x10); - zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 0xc); + zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; } @@ -192,7 +192,7 @@ static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A2(ZzArmRelocator *self, c zuint32 imm32 = (imm24 << 2) | (H << 1); zaddr target_address; target_address = insn_ctx->pc + imm32; - zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 0x8); + zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; } @@ -237,69 +237,3 @@ zbool zz_arm_relocator_write_one(ZzArmRelocator *self) { zz_arm_writer_put_bytes(self->output, (zbyte *)&insn_ctx->insn, insn_ctx->size); return TRUE; } - -// static zbool zz_arm_relocator_rewrite_ldr(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { - -// const cs_arm_op *dst = &insn_ctx->detail->operands[0]; -// const cs_arm_op *src = &insn_ctx->detail->operands[1]; -// zint disp; - -// if (src->type != ARM_OP_MEM || src->mem.base != ARM_REG_PC) -// return TRUE; - -// disp = src->mem.disp; - -// zz_arm_writer_put_ldr_b_reg_address(self->output, dst->reg, insn_ctx->pc); -// if (disp > 0xff) { -// zz_arm_writer_put_add_reg_reg_imm(self->output, dst->reg, dst->reg, 0xc00 | ((disp >> 8) & 0xff)); -// } -// zz_arm_writer_put_add_reg_reg_imm(self->output, dst->reg, dst->reg, disp & 0xff); -// zz_arm_writer_put_ldr_reg_reg_imm(self->output, dst->reg, dst->reg, 0); - -// return TRUE; -// } - -// static zbool zz_arm_relocator_rewrite_add(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { -// const cs_arm_op *dst = &insn_ctx->detail->operands[0]; -// const cs_arm_op *left = &insn_ctx->detail->operands[1]; -// const cs_arm_op *right = &insn_ctx->detail->operands[2]; - -// if (left->reg != ARM_REG_PC || right->type != ARM_OP_REG) -// return FALSE; - -// if (right->reg == dst->reg) { -// zz_arm_writer_put_add_reg_reg_imm(self->output, dst->reg, dst->reg, insn_ctx->pc & 0xff); -// zz_arm_writer_put_add_reg_reg_imm(self->output, dst->reg, dst->reg, 0xc00 | ((insn_ctx->pc >> 8) & 0xff)); -// zz_arm_writer_put_add_reg_reg_imm(self->output, dst->reg, dst->reg, 0x800 | ((insn_ctx->pc >> 16) & 0xff)); -// zz_arm_writer_put_add_reg_reg_imm(self->output, dst->reg, dst->reg, 0x400 | ((insn_ctx->pc >> 24) & 0xff)); -// } else { -// zz_arm_writer_put_ldr_reg_address(self->output, dst->reg, insn_ctx->pc); -// zz_arm_writer_put_add_reg_reg_imm(self->output, dst->reg, right->reg, 0); -// } - -// return TRUE; -// } - -// static zbool zz_arm_relocator_rewrite_b(ZzArmRelocator *self, cs_mode target_mode, ZzInstruction *insn_ctx) { -// cs_insn *insn_cs = insn_ctx->insn_cs; -// const cs_arm_op *target = &insn_ctx->detail->operands[0]; - -// if (target->type != ARM_OP_IMM) -// return FALSE; - -// zz_arm_writer_put_ldr_reg_address(self->output, ARM_REG_PC, -// (target_mode == CS_MODE_THUMB) ? target->imm | 1 : target->imm); -// return TRUE; -// } - -// static zbool zz_arm_relocator_rewrite_bl(ZzArmRelocator *self, cs_mode target_mode, ZzInstruction *insn_ctx) { -// const cs_arm_op *target = &insn_ctx->detail->operands[0]; - -// if (target->type != ARM_OP_IMM) -// return FALSE; - -// zz_arm_writer_put_ldr_reg_address(self->output, ARM_REG_LR, (zaddr)self->output->pc + (2 * 4)); -// zz_arm_writer_put_ldr_reg_address(self->output, ARM_REG_PC, -// (target_mode == CS_MODE_THUMB) ? target->imm | 1 : target->imm); -// return TRUE; -// } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c index 4871c86be..b71f91b22 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c @@ -254,8 +254,8 @@ zbool zz_thumb_relocator_rewrite_B_T4(ZzThumbRelocator *self, const ZzInstructio zuint32 J1 = get_insn_sub(insn_ctx->insn2, 13, 1); zuint32 imm10 = get_insn_sub(insn_ctx->insn1, 0, 10); zuint32 imm11 = get_insn_sub(insn_ctx->insn2, 0, 11); - zuint32 I1 = (~(J1 ^ S)); - zuint32 I2 = (~(J2 ^ S)); + zuint32 I1 = (~(J1 ^ S)) & 0x1; + zuint32 I2 = (~(J2 ^ S)) & 0x1; zuint32 imm32 = imm11 << 1 | imm10 << (1 + 11) | I1 << (1 + 11 + 6) | I2 << (1 + 11 + 6 + 1) | S << (1 + 11 + 6 + 1 + 1); zaddr target_address; @@ -275,14 +275,18 @@ zbool zz_thumb_relocator_rewrite_BLBLX_immediate_T1(ZzThumbRelocator *self, cons zuint32 J1 = get_insn_sub(insn_ctx->insn2, 13, 1); zuint32 imm10 = get_insn_sub(insn_ctx->insn1, 0, 10); zuint32 imm11 = get_insn_sub(insn_ctx->insn2, 0, 11); - zuint32 I1 = (~(J1 ^ S)); - zuint32 I2 = (~(J2 ^ S)); + zuint32 I1 = (~(J1 ^ S)) & 0x1; + zuint32 I2 = (~(J2 ^ S)) & 0x1; zuint32 imm32 = imm11 << 1 | imm10 << (1 + 11) | I1 << (1 + 11 + 6) | I2 << (1 + 11 + 6 + 1) | S << (1 + 11 + 6 + 1 + 1); zaddr target_address; + target_address = insn_ctx->pc + imm32; + if ((zaddr)insn_ctx->pc % 4) + target_address -= 2; - zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 2 * 4); + zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, + (insn_ctx->type == THUMB2_INSN) ? insn_ctx->pc : (insn_ctx->pc - 2)); zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); return TRUE; } @@ -296,15 +300,17 @@ zbool zz_thumb_relocator_rewrite_BLBLX_T2(ZzThumbRelocator *self, const ZzInstru zuint32 J2 = get_insn_sub(insn_ctx->insn2, 11, 1); zuint32 J1 = get_insn_sub(insn_ctx->insn2, 13, 1); zuint32 imm10_1 = get_insn_sub(insn_ctx->insn1, 0, 10); - zuint32 imm10_16 = get_insn_sub(insn_ctx->insn2, 1, 10); - zuint32 I1 = (~(J1 ^ S)); - zuint32 I2 = (~(J2 ^ S)); + zuint32 imm10_2 = get_insn_sub(insn_ctx->insn2, 1, 10); + zuint32 I1 = (~(J1 ^ S)) & 0x1; + zuint32 I2 = (~(J2 ^ S)) & 0x1; + ; + zuint32 H = get_insn_sub(insn_ctx->insn2, 0, 1); zuint32 imm32 = - imm10_1 << 2 | imm10_16 << (2 + 10) | I1 << (2 + 10 + 6) | I2 << (2 + 10 + 6 + 1) | S << (2 + 10 + 6 + 1 + 1); + imm10_2 << 2 | imm10_1 << (2 + 10) | I1 << (2 + 10 + 6) | I2 << (2 + 10 + 6 + 1) | S << (2 + 10 + 6 + 1 + 1); zaddr target_address; target_address = insn_ctx->pc + imm32; - zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 2 * 4); + zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc); zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); return TRUE; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c index 0911f2c32..a54aabb9a 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c @@ -181,18 +181,17 @@ void zz_arm_writer_put_bx_reg(ZzArmWriter *self, ZzARMReg reg) { void zz_arm_writer_put_nop(ZzArmWriter *self) { zz_arm_writer_put_instruction(self, 0xe320f000); } -zpointer zz_arm_writer_put_push_reg(ZzArmWriter *self, zint32 regs) { - zuint32 register_list; - register_list = regs & 0xFFFF; - - zz_arm_writer_put_instruction(self, 0b11011001001011010000000000000000 | register_list); +zpointer zz_arm_writer_put_push_reg(ZzArmWriter *self, ZzARMReg reg) { + ZzArmRegInfo ri; + zz_arm_register_describe(reg, &ri); + zz_arm_writer_put_instruction(self, 0b11100101001011010000000000000100 | ri.index << 12); return self->pc; } -zpointer zz_arm_writer_put_pop_reg(ZzArmWriter *self, zint32 regs) { - zuint32 register_list; - register_list = regs & 0xFFFF; +zpointer zz_arm_writer_put_pop_reg(ZzArmWriter *self, ZzARMReg reg) { + ZzArmRegInfo ri; + zz_arm_register_describe(reg, &ri); - zz_arm_writer_put_instruction(self, 0b11011000101111010000000000000000 | register_list); + zz_arm_writer_put_instruction(self, 0b11100100100111010000000000000100 | ri.index << 12); return self->pc; } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h index c62227a15..37694e3b9 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h @@ -62,7 +62,7 @@ void zz_arm_writer_put_ldr_reg_reg_imm_A1(ZzArmWriter *self, ZzARMReg dst_reg, Z void zz_arm_writer_put_ldr_reg_address(ZzArmWriter *self, ZzARMReg reg, zaddr address); void zz_arm_writer_put_add_reg_reg_imm(ZzArmWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, zuint32 imm); void zz_arm_writer_put_sub_reg_reg_imm(ZzArmWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, zuint32 imm); -zpointer zz_arm_writer_put_push_reg(ZzArmWriter *self, zint32 regs); -zpointer zz_arm_writer_put_pop_reg(ZzArmWriter *self, zint32 regs); +zpointer zz_arm_writer_put_push_reg(ZzArmWriter *self, ZzARMReg reg); +zpointer zz_arm_writer_put_pop_reg(ZzArmWriter *self, ZzARMReg reg); #endif \ No newline at end of file From 16fdce7b49dbb9b19111979f81267a240417ba9e Mon Sep 17 00:00:00 2001 From: caokai Date: Thu, 2 Nov 2017 11:13:33 +0800 Subject: [PATCH 007/334] =?UTF-8?q?=E4=BD=BF=E6=8F=92=E4=BB=B6=E8=83=BD?= =?UTF-8?q?=E5=A4=9F=E6=94=B6=E5=88=B0=E8=A7=A3=E9=94=81=E5=B1=8F=E5=B9=95?= =?UTF-8?q?=E5=B9=BF=E6=92=ADandroid.intent.action.USER=5FPRESENT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VirtualApp/build.gradle | 8 ++++++++ .../com/lody/virtual/client/env/SpecialComponentList.java | 1 + .../com/lody/virtual/server/pm/PrivilegeAppOptimizer.java | 1 + 3 files changed, 10 insertions(+) diff --git a/VirtualApp/build.gradle b/VirtualApp/build.gradle index 7aa701d03..95d25385a 100644 --- a/VirtualApp/build.gradle +++ b/VirtualApp/build.gradle @@ -3,6 +3,10 @@ buildscript { repositories { jcenter() + maven { + url 'https://maven.google.com/' + name 'Google' + } } dependencies { classpath 'com.android.tools.build:gradle:2.3.1' @@ -19,6 +23,10 @@ allprojects { maven { url "https://jitpack.io" } + maven { + url 'https://maven.google.com/' + name 'Google' + } } } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/env/SpecialComponentList.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/env/SpecialComponentList.java index 9d1872b22..91c95e88f 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/env/SpecialComponentList.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/env/SpecialComponentList.java @@ -43,6 +43,7 @@ public final class SpecialComponentList { SYSTEM_BROADCAST_ACTION.add(Intent.ACTION_BATTERY_OKAY); SYSTEM_BROADCAST_ACTION.add(Intent.ACTION_POWER_CONNECTED); SYSTEM_BROADCAST_ACTION.add(Intent.ACTION_POWER_DISCONNECTED); + SYSTEM_BROADCAST_ACTION.add(Intent.ACTION_USER_PRESENT); SYSTEM_BROADCAST_ACTION.add("android.provider.Telephony.SMS_RECEIVED"); SYSTEM_BROADCAST_ACTION.add("android.provider.Telephony.SMS_DELIVER"); SYSTEM_BROADCAST_ACTION.add("android.net.wifi.STATE_CHANGE"); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/PrivilegeAppOptimizer.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/PrivilegeAppOptimizer.java index 20b84cf5a..02ce3fbab 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/PrivilegeAppOptimizer.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/PrivilegeAppOptimizer.java @@ -1,6 +1,7 @@ package com.lody.virtual.server.pm; import android.content.Intent; +import android.util.Log; import com.lody.virtual.client.stub.VASettings; import com.lody.virtual.os.VUserHandle; From c7ac9fd5e46f165bee12fc33bc553360e7623a28 Mon Sep 17 00:00:00 2001 From: keyongyu <247321453@qq.com> Date: Wed, 8 Nov 2017 20:15:35 +0800 Subject: [PATCH 008/334] =?UTF-8?q?BitmapReflectionAction=20=E5=92=8CRefle?= =?UTF-8?q?ctionAction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lody/virtual/server/notification/NotificationFixer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/NotificationFixer.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/NotificationFixer.java index 499c3444f..84e3c616d 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/NotificationFixer.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/NotificationFixer.java @@ -142,8 +142,7 @@ boolean fixRemoteViewActions(Context appContext, boolean installed, final Remote mActions.remove(action); continue; } - if (ReflectionActionCompat.isInstance(action) - || (action.getClass().getSimpleName().endsWith("ReflectionAction"))) { + if (ReflectionActionCompat.isInstance(action)) { int viewId = Reflect.on(action).get("viewId"); String methodName = Reflect.on(action).get("methodName"); From 1bcc0715c94f94710dad6441967a7a641dd37782 Mon Sep 17 00:00:00 2001 From: asLody Date: Thu, 9 Nov 2017 17:18:15 +0800 Subject: [PATCH 009/334] [native-code] : update HookZz library. --- .../hook/proxies/am/ActivityManagerStub.java | 21 - VirtualApp/lib/src/main/jni/HookZz/.gitignore | 61 -- .../lib/src/main/jni/HookZz/.gitmodules | 3 - VirtualApp/lib/src/main/jni/HookZz/Makefile | 2 +- .../lib/src/main/jni/HookZz/src/allocator.c | 7 +- .../lib/src/main/jni/HookZz/src/interceptor.c | 3 +- .../src/platforms/arch-arm/instructions.c | 3 +- .../src/platforms/arch-arm/instructions.h | 6 + .../src/platforms/arch-arm/reader-thumb.c | 6 +- .../src/platforms/arch-arm/reader-thumb.h | 1 + .../src/platforms/arch-arm/relocator-arm.c | 148 ++++- .../src/platforms/arch-arm/relocator-arm.h | 11 +- .../src/platforms/arch-arm/relocator-thumb.c | 229 +++++-- .../src/platforms/arch-arm/relocator-thumb.h | 12 +- .../src/platforms/arch-arm/writer-arm.c | 39 +- .../src/platforms/arch-arm/writer-arm.h | 9 +- .../src/platforms/arch-arm/writer-thumb.c | 240 ++++---- .../src/platforms/arch-arm/writer-thumb.h | 69 ++- .../src/platforms/arch-arm64/instructions.c | 3 +- .../src/platforms/arch-arm64/instructions.h | 6 + .../platforms/arch-arm64/relocator-arm64.c | 123 +++- .../platforms/arch-arm64/relocator-arm64.h | 25 +- .../src/platforms/arch-arm64/writer-arm64.c | 72 ++- .../src/platforms/arch-arm64/writer-arm64.h | 27 +- .../platforms/backend-arm/interceptor-arm.c | 550 +++++++++++++++++ .../platforms/backend-arm/interceptor-arm.h | 5 + .../src/platforms/backend-arm/thunker-arm.c | 91 +-- .../platforms/backend-arm/trampoline-arm.c | 577 ------------------ .../platforms/backend-arm/trampoline-arm.h | 15 - ...trampoline-arm64.c => interceptor-arm64.c} | 345 ++++------- .../backend-arm64/interceptor-arm64.h | 3 + .../platforms/backend-arm64/thunker-arm64.c | 90 +-- .../lib/src/main/jni/HookZz/src/stack.c | 14 +- .../lib/src/main/jni/HookZz/src/writer.h | 17 +- .../lib/src/main/jni/HookZz/src/zzdefs.h | 4 +- .../src/zzdeps/darwin/macho-utils-darwin.c | 40 +- .../src/zzdeps/darwin/memory-utils-darwin.c | 4 +- .../src/zzdeps/linux/memory-utils-linux.c | 4 +- .../src/zzdeps/posix/thread-utils-posix.c | 11 +- .../jni/HookZz/tests/arm-insn-fix/makefile | 19 + .../HookZz/tests/arm-insn-fix/test_insn_fix.c | 106 ++++ .../jni/HookZz/tests/arm64-insn-fix/makefile | 19 + .../tests/arm64-insn-fix/test_insn_fix.c | 40 ++ 43 files changed, 1717 insertions(+), 1363 deletions(-) delete mode 100644 VirtualApp/lib/src/main/jni/HookZz/.gitignore delete mode 100644 VirtualApp/lib/src/main/jni/HookZz/.gitmodules create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c delete mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c delete mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.h rename VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/{trampoline-arm64.c => interceptor-arm64.c} (52%) create mode 100644 VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/makefile create mode 100644 VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/test_insn_fix.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/makefile create mode 100644 VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/test_insn_fix.c diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/ActivityManagerStub.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/ActivityManagerStub.java index 077514925..329f54207 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/ActivityManagerStub.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/ActivityManagerStub.java @@ -115,27 +115,6 @@ public Object call(Object who, Method method, Object... args) throws Throwable { return _infos; } }); - addMethodProxy(new StaticMethodProxy("getRunningTasks") { - @Override - public Object call(Object who, Method method, Object... args) throws Throwable { - Object _infos = method.invoke(who, args); - //noinspection unchecked - List infos = - ParceledListSliceCompat.isReturnParceledListSlice(method) - ? ParceledListSlice.getList.call(_infos) - : (List) _infos; - for (ActivityManager.RunningTaskInfo info : infos) { - AppTaskInfo taskInfo = VActivityManager.get().getTaskInfo(info.id); - if (taskInfo == null) { - continue; - } - info.description = "Virtual"; - info.topActivity = taskInfo.topActivity; - info.baseActivity = taskInfo.baseActivity; - } - return _infos; - } - }); } } diff --git a/VirtualApp/lib/src/main/jni/HookZz/.gitignore b/VirtualApp/lib/src/main/jni/HookZz/.gitignore deleted file mode 100644 index 5713f6d07..000000000 --- a/VirtualApp/lib/src/main/jni/HookZz/.gitignore +++ /dev/null @@ -1,61 +0,0 @@ -.DS_Store -build/ -darwin.ios.release.mk -.idea/ -.vscode/ -cmake-build-debug/ -MachoParser.xcworkspace/ -CMakeLists.txt - -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf diff --git a/VirtualApp/lib/src/main/jni/HookZz/.gitmodules b/VirtualApp/lib/src/main/jni/HookZz/.gitmodules deleted file mode 100644 index 20dc32052..000000000 --- a/VirtualApp/lib/src/main/jni/HookZz/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "tools/deps/MachoParser"] - path = tools/deps/MachoParser - url = https://github.com/jmpews/MachoParser.git diff --git a/VirtualApp/lib/src/main/jni/HookZz/Makefile b/VirtualApp/lib/src/main/jni/HookZz/Makefile index 5ad7f240e..175c71434 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/Makefile +++ b/VirtualApp/lib/src/main/jni/HookZz/Makefile @@ -8,7 +8,7 @@ HOOKZZ_DIR := $(abspath .) LOCAL_PATH := $(abspath .) OUTPUT_DIR := $(abspath build) -CFLAGS ?= -O0 -g -std=c99 +CFLAGS ?= -O0 -g CXXFLAGS = $(CFLAGS) -stdlib=libc++ -std=c++11 -gmodules LDFLAGS ?= LIBS_CFLAGS ?= -fPIC diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/allocator.c b/VirtualApp/lib/src/main/jni/HookZz/src/allocator.c index deee6fcf2..2dbbe6ed4 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/allocator.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/allocator.c @@ -144,8 +144,9 @@ ZZSTATUS ZzAddMemoryPage(ZzAllocator *allocator, ZzMemoryPage *page) { ZzCodeSlice *ZzNewCodeSlice(ZzAllocator *allocator, zsize code_slice_size) { ZzCodeSlice *code_slice = NULL; ZzMemoryPage *page = NULL; + int i; - for (int i = 0; i < allocator->size; i++) { + for (i = 0; i < allocator->size; i++) { page = allocator->memory_pages[i]; // 1. page is initialized // 2. can't be codecave @@ -195,8 +196,8 @@ ZzCodeSlice *ZzNewNearCodeSlice(ZzAllocator *allocator, zaddr address, zsize red zsize code_slice_size) { ZzCodeSlice *code_slice = NULL; ZzMemoryPage *page = NULL; - - for (int i = 0; i < allocator->size; i++) { + int i; + for (i = 0; i < allocator->size; i++) { page = allocator->memory_pages[i]; // 1. page is initialized // 2. can't be codecave diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c index c773cd822..10464951a 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c @@ -58,7 +58,8 @@ ZzHookFunctionEntry *ZzFindHookFunctionEntry(zpointer target_ptr) { ZzHookFunctionEntrySet *hook_function_entry_set = &(interceptor->hook_function_entry_set); - for (int i = 0; i < hook_function_entry_set->size; ++i) { + int i; + for (i = 0; i < hook_function_entry_set->size; ++i) { if ((hook_function_entry_set->entries)[i] && target_ptr == (hook_function_entry_set->entries)[i]->target_ptr) { return (hook_function_entry_set->entries)[i]; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c index 6456bfdb1..4e5588d27 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c @@ -7,7 +7,8 @@ zuint32 get_insn_sub(zuint32 insn, int start, int length) { return (insn >> star zbool insn_equal(zuint32 insn, char *opstr) { zuint32 mask = 0, value = 0; zsize length = strlen(opstr); - for (int i = length - 1, j = 0; i >= 0 && j < length; i--, j++) { + int i, j; + for (i = length - 1, j = 0; i >= 0 && j < length; i--, j++) { if (opstr[i] == 'x') { mask = mask | (0 << j); } else if (opstr[i] == '0') { diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.h index 835aaa9a5..f8b41e269 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.h @@ -39,6 +39,12 @@ typedef struct _Instruction { zuint16 insn2; } ZzInstruction; +typedef struct _ZzRelocateInstruction { + const ZzInstruction *insn_ctx; + zaddr relocated_offset; + zsize relocated_length; +} ZzRelocateInstruction; + zuint32 get_insn_sub(zuint32 insn, int start, int length); zbool insn_equal(zuint32 insn, char *opstr); diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c index 9f9f2819a..652433b79 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.c @@ -53,8 +53,10 @@ zpointer zz_thumb_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer // A5 ARM Instruction Set Encoding // A5.3 Load/store word and unsigned byte THUMBInsnType GetTHUMBInsnType(zuint16 insn1, zuint16 insn2) { - // zuint32 insn1 = insn_ctx->insn1; - zuint32 op, op1; + + if (!insn_is_thumb2(insn1) && insn_equal(insn1, "1011x0x1xxxxxxxx")) { + return THUMB_INS_CBNZ_CBZ; + } if (!insn_is_thumb2(insn1) && insn_equal(insn1, "01000100xxxxxxxx")) { return THUMB_INS_ADD_register_T2; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h index 787ccb0c7..3d1dee803 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-thumb.h @@ -27,6 +27,7 @@ #include "zzdeps/zz.h" typedef enum _THUMBInsnType { + THUMB_INS_CBNZ_CBZ, THUMB_INS_ADD_register_T2, THUMB_INS_LDR_literal_T1, THUMB_INS_LDR_literal_T2, diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c index a274ccffd..f5cd99119 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c @@ -24,31 +24,43 @@ void zz_arm_relocator_init(ZzArmRelocator *relocator, zpointer input_code, ZzArmWriter *output) { relocator->inpos = 0; relocator->outpos = 0; - relocator->input_start = input_code; relocator->input_cur = input_code; relocator->input_pc = (zaddr)input_code; + relocator->output = output; + relocator->relocate_literal_insns_size = 0; + relocator->try_relocated_length = 0; relocator->input_insns = (ZzInstruction *)malloc(MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); memset(relocator->input_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); - - relocator->output = output; + relocator->output_insns = + (ZzRelocateInstruction *)malloc(MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + memset(relocator->output_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + relocator->relocate_literal_insns = + (ZzLiteralInstruction **)malloc(MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); + memset(relocator->relocate_literal_insns, 0, MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); } void zz_arm_relocator_reset(ZzArmRelocator *self, zpointer input_code, ZzArmWriter *output) { self->input_cur = input_code; self->input_start = input_code; self->input_pc = (zaddr)input_code; - self->inpos = 0; self->outpos = 0; - self->output = output; + self->relocate_literal_insns_size = 0; + self->try_relocated_length = 0; + + memset(self->input_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); + memset(self->output_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + memset(self->relocate_literal_insns, 0, MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); } zsize zz_arm_relocator_read_one(ZzArmRelocator *self, ZzInstruction *instruction) { ZzInstruction *insn_ctx = &self->input_insns[self->inpos]; + ZzRelocateInstruction *re_insn_ctx = &self->output_insns[self->inpos]; + re_insn_ctx->insn_ctx = insn_ctx; zz_arm_reader_read_one_instruction(insn_ctx, self->input_cur); // switch (1) {} @@ -64,17 +76,76 @@ zsize zz_arm_relocator_read_one(ZzArmRelocator *self, ZzInstruction *instruction return self->input_cur - self->input_start; } void zz_arm_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes) { - *max_bytes = 16; + int tmp_size = 0; + zpointer target_addr; + ZzInstruction insn_ctx; + zbool early_end = FALSE; + target_addr = (zpointer)address; + + do { + zz_arm_reader_read_one_instruction(&insn_ctx, target_addr); + switch (GetARMInsnType(insn_ctx.insn)) { + case ARM_INS_B_A1: { + zuint32 cond = get_insn_sub(insn_ctx.insn, 28, 4); + if (cond == 0xE) + early_end = TRUE; + }; break; + default:; + } + tmp_size += insn_ctx.size; + target_addr = target_addr + insn_ctx.size; + } while (tmp_size < min_bytes); + + if (early_end) { + *max_bytes = tmp_size; + } return; } +zaddr zz_arm_relocator_get_insn_relocated_offset(ZzArmRelocator *self, zaddr address) { + const ZzInstruction *insn_ctx; + const ZzRelocateInstruction *re_insn_ctx; + int i; + for (i = 0; i < self->inpos; i++) { + re_insn_ctx = &self->output_insns[i]; + insn_ctx = re_insn_ctx->insn_ctx; + if (insn_ctx->address == address && re_insn_ctx->relocated_offset) { + return re_insn_ctx->relocated_offset; + } + } + return 0; +} + +void zz_arm_relocator_relocate_writer(ZzArmRelocator *relocator, zaddr code_address) { + ZzArmWriter *arm_writer; + arm_writer = relocator->output; + if (relocator->relocate_literal_insns_size) { + int i; + zaddr literal_address, relocated_offset, relocated_address, *literal_address_ptr; + for (i = 0; i < relocator->relocate_literal_insns_size; i++) { + literal_address_ptr = (zaddr *)relocator->relocate_literal_insns[i]->literal_address_ptr; + literal_address = *literal_address_ptr; + relocated_offset = zz_arm_relocator_get_insn_relocated_offset(relocator, literal_address); + if (relocated_offset) { + relocated_address = code_address + relocated_offset; + *literal_address_ptr = relocated_address; + } + } + } +} + void zz_arm_relocator_write_all(ZzArmRelocator *self) { zuint count = 0; + zuint outpos = self->outpos; + ZzArmWriter arm_writer = *self->output; + while (zz_arm_relocator_write_one(self)) count++; } + // PAGE: A8-312 -static zbool zz_arm_relocator_rewrite_ADD_register_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm_relocator_rewrite_ADD_register_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 Rn_ndx, Rd_ndx, Rm_ndx; @@ -95,7 +166,8 @@ static zbool zz_arm_relocator_rewrite_ADD_register_A1(ZzArmRelocator *self, cons } // PAGE: A8-410 -static zbool zz_arm_relocator_rewrite_LDR_literal_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm_relocator_rewrite_LDR_literal_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm12 = get_insn_sub(insn, 0, 12); zuint32 imm32 = imm12; @@ -113,7 +185,8 @@ static zbool zz_arm_relocator_rewrite_LDR_literal_A1(ZzArmRelocator *self, const } // PAGE: A8-322 -static zbool zz_arm_relocator_rewrite_ADR_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm_relocator_rewrite_ADR_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm12 = get_insn_sub(insn, 0, 12); zuint32 imm32 = imm12; @@ -125,7 +198,8 @@ static zbool zz_arm_relocator_rewrite_ADR_A1(ZzArmRelocator *self, const ZzInstr } // PAGE: A8-322 -static zbool zz_arm_relocator_rewrite_ADR_A2(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm_relocator_rewrite_ADR_A2(ZzArmRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm12 = get_insn_sub(insn, 0, 12); zuint32 imm32 = imm12; @@ -143,7 +217,8 @@ static zbool zz_arm_relocator_rewrite_ADR_A2(ZzArmRelocator *self, const ZzInstr // 0x010 : remain code // PAGE: A8-334 -static zbool zz_arm_relocator_rewrite_B_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm_relocator_rewrite_B_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm24 = get_insn_sub(insn, 0, 24); zuint32 imm32 = imm24 << 2; @@ -170,64 +245,84 @@ static zbool zz_arm_relocator_rewrite_B_A1(ZzArmRelocator *self, const ZzInstruc // 0x01c : remain code // PAGE: A8-348 -static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A1(ZzArmRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm24 = get_insn_sub(insn, 0, 24); zuint32 imm32 = imm24 << 2; zaddr target_address; - target_address = insn_ctx->pc + imm32; + target_address = ALIGN_4(insn_ctx->pc) + imm32; - zz_arm_writer_put_instruction(self->output, (insn & 0xFF000000) | 0); - zz_arm_writer_put_b_imm(self->output, 0x10); - zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4); + // CurrentInstrSet = thumb + // targetInstrSet = arm + + // convert 'bl' to 'b', but save 'cond' + zz_arm_writer_put_instruction(self->output, (insn & 0xF0000000) | 0b1010 << 24 | 0); + + ZzArmWriter ouput_bak = *self->output; + zz_arm_writer_put_b_imm(self->output, 0); + + ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); + zz_arm_writer_put_ldr_b_reg_relocate_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4, literal_insn_ptr); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); + + // overwrite `zz_arm_writer_put_b_imm` + zz_arm_writer_put_b_imm(&ouput_bak, self->output->pc - ouput_bak.pc - 8); return TRUE; } // PAGE: A8-348 -static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A2(ZzArmRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A2(ZzArmRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 H = get_insn_sub(insn, 24, 1); zuint32 imm24 = get_insn_sub(insn, 0, 24); zuint32 imm32 = (imm24 << 2) | (H << 1); zaddr target_address; target_address = insn_ctx->pc + imm32; - zz_arm_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4); + + ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); + zz_arm_writer_put_ldr_b_reg_relocate_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4, literal_insn_ptr); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; } zbool zz_arm_relocator_write_one(ZzArmRelocator *self) { const ZzInstruction *insn_ctx; + ZzRelocateInstruction *re_insn_ctx; zbool rewritten = FALSE; if (self->inpos != self->outpos) { insn_ctx = &self->input_insns[self->outpos]; + re_insn_ctx = &self->output_insns[self->outpos]; + self->outpos++; } else return FALSE; + re_insn_ctx->relocated_offset = (zaddr)self->output->pc - (zaddr)self->output->base; + switch (GetARMInsnType(insn_ctx->insn)) { case ARM_INS_ADD_register_A1: - rewritten = zz_arm_relocator_rewrite_ADD_register_A1(self, insn_ctx); + rewritten = zz_arm_relocator_rewrite_ADD_register_A1(self, insn_ctx, re_insn_ctx); break; case ARM_INS_LDR_literal_A1: - rewritten = zz_arm_relocator_rewrite_LDR_literal_A1(self, insn_ctx); + rewritten = zz_arm_relocator_rewrite_LDR_literal_A1(self, insn_ctx, re_insn_ctx); break; case ARM_INS_ADR_A1: - rewritten = zz_arm_relocator_rewrite_ADR_A1(self, insn_ctx); + rewritten = zz_arm_relocator_rewrite_ADR_A1(self, insn_ctx, re_insn_ctx); break; case ARM_INS_ADR_A2: - rewritten = zz_arm_relocator_rewrite_ADR_A2(self, insn_ctx); + rewritten = zz_arm_relocator_rewrite_ADR_A2(self, insn_ctx, re_insn_ctx); break; case ARM_INS_B_A1: - rewritten = zz_arm_relocator_rewrite_B_A1(self, insn_ctx); + rewritten = zz_arm_relocator_rewrite_B_A1(self, insn_ctx, re_insn_ctx); break; case ARM_INS_BLBLX_immediate_A1: - rewritten = zz_arm_relocator_rewrite_BLBLX_immediate_A1(self, insn_ctx); + rewritten = zz_arm_relocator_rewrite_BLBLX_immediate_A1(self, insn_ctx, re_insn_ctx); break; case ARM_INS_BLBLX_immediate_A2: - rewritten = zz_arm_relocator_rewrite_BLBLX_immediate_A2(self, insn_ctx); + rewritten = zz_arm_relocator_rewrite_BLBLX_immediate_A2(self, insn_ctx, re_insn_ctx); break; case ARM_UNDEF: rewritten = FALSE; @@ -235,5 +330,8 @@ zbool zz_arm_relocator_write_one(ZzArmRelocator *self) { } if (!rewritten) zz_arm_writer_put_bytes(self->output, (zbyte *)&insn_ctx->insn, insn_ctx->size); + + re_insn_ctx->relocated_length = + (zaddr)self->output->pc - (zaddr)self->output->base - (zaddr)re_insn_ctx->relocated_offset; return TRUE; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.h index f8df420e9..a1ee866ed 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.h @@ -33,14 +33,18 @@ #include "zzdeps/zz.h" typedef struct _ZzArmRelocator { + zbool try_relocated_again; + zsize try_relocated_length; zpointer input_start; zpointer input_cur; zaddr input_pc; - ZzInstruction *input_insns; - ZzArmWriter *output; - zuint inpos; zuint outpos; + ZzInstruction *input_insns; + ZzRelocateInstruction *output_insns; + ZzLiteralInstruction **relocate_literal_insns; + zsize relocate_literal_insns_size; + ZzArmWriter *output; } ZzArmRelocator; void zz_arm_relocator_init(ZzArmRelocator *relocator, zpointer input_code, ZzArmWriter *output); @@ -49,4 +53,5 @@ void zz_arm_relocator_write_all(ZzArmRelocator *self); zsize zz_arm_relocator_read_one(ZzArmRelocator *self, ZzInstruction *instruction); void zz_arm_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes); zbool zz_arm_relocator_write_one(ZzArmRelocator *self); +void zz_arm_relocator_relocate_writer(ZzArmRelocator *relocator, zaddr code_address); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c index b71f91b22..c5fb32259 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c @@ -21,31 +21,46 @@ #define MAX_RELOCATOR_INSTRUCIONS_SIZE 64 -void zz_thumb_relocator_init(ZzThumbRelocator *relocator, zpointer input_code, ZzThumbWriter *writer) { +void zz_thumb_relocator_init(ZzThumbRelocator *relocator, zpointer input_code, ZzThumbWriter *output) { relocator->inpos = 0; relocator->outpos = 0; - relocator->input_start = input_code; relocator->input_cur = input_code; relocator->input_pc = (zaddr)input_code; + relocator->output = output; + relocator->relocate_literal_insns_size = 0; + relocator->try_relocated_length = 0; + relocator->input_insns = (ZzInstruction *)malloc(MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); memset(relocator->input_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); + relocator->output_insns = + (ZzRelocateInstruction *)malloc(MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + memset(relocator->output_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + relocator->relocate_literal_insns = + (ZzLiteralInstruction **)malloc(MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); + memset(relocator->relocate_literal_insns, 0, MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); } void zz_thumb_relocator_reset(ZzThumbRelocator *self, zpointer input_code, ZzThumbWriter *output) { self->input_cur = input_code; self->input_start = input_code; self->input_pc = (zaddr)input_code; - self->inpos = 0; self->outpos = 0; - self->output = output; + self->relocate_literal_insns_size = 0; + self->try_relocated_length = 0; + + memset(self->input_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); + memset(self->output_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + memset(self->relocate_literal_insns, 0, MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); } zsize zz_thumb_relocator_read_one(ZzThumbRelocator *self, ZzInstruction *instruction) { ZzInstruction *insn_ctx = &self->input_insns[self->inpos]; + ZzRelocateInstruction *re_insn_ctx = &self->output_insns[self->inpos]; + re_insn_ctx->insn_ctx = insn_ctx; zz_thumb_reader_read_one_instruction(insn_ctx, self->input_cur); // switch (1) {} @@ -62,18 +77,118 @@ zsize zz_thumb_relocator_read_one(ZzThumbRelocator *self, ZzInstruction *instruc } void zz_thumb_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes) { - *max_bytes = 16; + int tmp_size = 0; + zbool is_thumb; + zpointer target_addr; + ZzInstruction insn_ctx; + zbool early_end = FALSE; + is_thumb = INSTRUCTION_IS_THUMB((zaddr)address); + target_addr = (zpointer)address; + + do { + zz_thumb_reader_read_one_instruction(&insn_ctx, target_addr); + switch (GetTHUMBInsnType(insn_ctx.insn1, insn_ctx.insn2)) { + case THUMB_INS_B_T2: + early_end = TRUE; + break; + case THUMB_INS_B_T4: + early_end = TRUE; + break; + default:; + } + tmp_size += insn_ctx.size; + target_addr = target_addr + insn_ctx.size; + } while (tmp_size < min_bytes); + + if (early_end) { + *max_bytes = tmp_size; + } return; } +zaddr zz_thumb_relocator_get_insn_relocated_offset(ZzThumbRelocator *self, zaddr address) { + const ZzInstruction *insn_ctx; + const ZzRelocateInstruction *re_insn_ctx; + int i; + + for (i = 0; i < self->inpos; i++) { + re_insn_ctx = &self->output_insns[i]; + insn_ctx = re_insn_ctx->insn_ctx; + if (insn_ctx->address == address && re_insn_ctx->relocated_offset) { + return re_insn_ctx->relocated_offset; + } + } + return 0; +} + +void zz_thumb_relocator_relocate_writer(ZzThumbRelocator *relocator, zaddr code_address) { + ZzThumbWriter *thumb_writer; + thumb_writer = relocator->output; + if (relocator->relocate_literal_insns_size) { + int i; + zaddr literal_address, relocated_offset, relocated_address, *literal_address_ptr; + for (i = 0; i < relocator->relocate_literal_insns_size; i++) { + literal_address_ptr = (zaddr *)relocator->relocate_literal_insns[i]->literal_address_ptr; + literal_address = *literal_address_ptr; + relocated_offset = zz_thumb_relocator_get_insn_relocated_offset(relocator, literal_address & ~(zaddr)1); + if (relocated_offset) { + relocated_address = code_address + relocated_offset + 1; + *literal_address_ptr = relocated_address; + } + } + } +} + void zz_thumb_relocator_write_all(ZzThumbRelocator *self) { zuint count = 0; + zuint outpos = self->outpos; + ZzThumbWriter thumb_writer = *self->output; + while (zz_thumb_relocator_write_one(self)) count++; } +// A8-357 +// 0: cbz #0 +// 2: b #6 +// 4: ldr pc, #0 +// 8: .long ? +// c: next insn +static zbool zz_thumb_relocator_rewrite_CBNZ_CBZ(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { + + zuint32 insn1 = insn_ctx->insn1; + zuint16 op, i, imm5, Rn_ndx; + zuint32 imm32, nonzero; + + op = get_insn_sub(insn1, 11, 1); + i = get_insn_sub(insn1, 9, 1); + imm5 = get_insn_sub(insn1, 3, 5); + Rn_ndx = get_insn_sub(insn1, 0, 3); + + imm32 = imm5 << 1 | i << (5 + 1); + nonzero = (op == 1); + + zaddr target_address = insn_ctx->pc + imm32; + + /* for align , simple solution, maybe the correct solution is get `ldr_reg_address` length and adjust the immediate + * of `b_imm`. */ + if ((zaddr)self->output->pc % 4) { + zz_thumb_writer_put_nop(self->output); + } + + zz_thumb_writer_put_instruction(self->output, (insn1 & 0b1111110100000111) | 0); + zz_thumb_writer_put_b_imm(self->output, 0x6); + + ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); + zz_thumb_writer_put_ldr_reg_relocate_address(self->output, ZZ_ARM_REG_PC, target_address + 1, literal_insn_ptr); + // zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); + return TRUE; +} + // PAGE: A8-310 -zbool zz_thumb_relocator_rewrite_ADD_register_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_thumb_relocator_rewrite_ADD_register_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint16 Rm_ndx, Rdn_ndx, DN, Rd_ndx; @@ -85,6 +200,7 @@ zbool zz_thumb_relocator_rewrite_ADD_register_T2(ZzThumbRelocator *self, const Z if (Rm_ndx != ZZ_ARM_REG_PC) { return FALSE; } + // push R7 zz_thumb_writer_put_push_reg(self->output, 1 << 7); // zz_thumb_writer_put_str_index_reg_reg_offset(self->output, ZZ_ARM_REG_R7, ZZ_ARM_REG_SP, -4, 1); @@ -94,15 +210,17 @@ zbool zz_thumb_relocator_rewrite_ADD_register_T2(ZzThumbRelocator *self, const Z // pop R7 zz_thumb_writer_put_pop_reg(self->output, 1 << 7); // zz_thumb_writer_put_ldr_index_reg_reg_offset(self->output, ZZ_ARM_REG_R7, ZZ_ARM_REG_SP, 4, 0); + return TRUE; } // PAGE: A8-410 -zbool zz_thumb_relocator_rewrite_LDR_literal_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_LDR_literal_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 imm8 = get_insn_sub(insn1, 0, 8); zuint32 imm32 = imm8 << 2; - zaddr target_address = insn_ctx->pc + imm32; + zaddr target_address = ALIGN_4(insn_ctx->pc) + imm32; int Rt_ndx = get_insn_sub(insn1, 8, 3); zz_thumb_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); zz_thumb_writer_put_ldr_reg_reg_offset(self->output, Rt_ndx, Rt_ndx, 0); @@ -110,7 +228,8 @@ zbool zz_thumb_relocator_rewrite_LDR_literal_T1(ZzThumbRelocator *self, const Zz } // PAGE: A8-410 -zbool zz_thumb_relocator_rewrite_LDR_literal_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_LDR_literal_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 insn2 = insn_ctx->insn2; @@ -120,9 +239,9 @@ zbool zz_thumb_relocator_rewrite_LDR_literal_T2(ZzThumbRelocator *self, const Zz zbool add = get_insn_sub(insn_ctx->insn1, 7, 1) == 1; zaddr target_address; if (add) - target_address = insn_ctx->pc + imm32; + target_address = ALIGN_4(insn_ctx->pc) + imm32; else - target_address = insn_ctx->pc - imm32; + target_address = ALIGN_4(insn_ctx->pc) - imm32; int Rt_ndx = get_insn_sub(insn_ctx->insn2, 12, 4); zz_thumb_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); @@ -131,7 +250,8 @@ zbool zz_thumb_relocator_rewrite_LDR_literal_T2(ZzThumbRelocator *self, const Zz } // PAGE: A8-322 -zbool zz_thumb_relocator_rewrite_ADR_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_ADR_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 imm8 = get_insn_sub(insn1, 0, 8); @@ -144,7 +264,8 @@ zbool zz_thumb_relocator_rewrite_ADR_T1(ZzThumbRelocator *self, const ZzInstruct } // PAGE: A8-322 -zbool zz_thumb_relocator_rewrite_ADR_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_ADR_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 insn2 = insn_ctx->insn2; @@ -159,7 +280,8 @@ zbool zz_thumb_relocator_rewrite_ADR_T2(ZzThumbRelocator *self, const ZzInstruct } // PAGE: A8-322 -zbool zz_thumb_relocator_rewrite_ADR_T3(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_ADR_T3(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 insn2 = insn_ctx->insn2; @@ -180,7 +302,8 @@ zbool zz_thumb_relocator_rewrite_ADR_T3(ZzThumbRelocator *self, const ZzInstruct // 0x00c : remain code // PAGE: A8-334 -zbool zz_thumb_relocator_rewrite_B_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_B_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; // zuint32 insn2 = insn_ctx->insn2; @@ -195,19 +318,20 @@ zbool zz_thumb_relocator_rewrite_B_T1(ZzThumbRelocator *self, const ZzInstructio } zz_thumb_writer_put_instruction(self->output, (insn1 & 0xFF00) | 0); zz_thumb_writer_put_b_imm(self->output, 0x6); - zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); + zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); return TRUE; } // PAGE: A8-334 -zbool zz_thumb_relocator_rewrite_B_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_B_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 imm11 = get_insn_sub(insn1, 0, 11); zuint32 imm32 = imm11 << 1; zaddr target_address = insn_ctx->pc + imm32; - zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); + zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); return TRUE; } @@ -218,7 +342,8 @@ zbool zz_thumb_relocator_rewrite_B_T2(ZzThumbRelocator *self, const ZzInstructio // 0x010 : remain code // PAGE: A8-334 -zbool zz_thumb_relocator_rewrite_B_T3(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_B_T3(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 insn2 = insn_ctx->insn2; @@ -240,12 +365,13 @@ zbool zz_thumb_relocator_rewrite_B_T3(ZzThumbRelocator *self, const ZzInstructio zz_thumb_writer_put_instruction(self->output, insn_ctx->insn1 & 0b1111101111000000); zz_thumb_writer_put_instruction(self->output, (insn_ctx->insn2 & 0b1101000000000000) | 0b1); zz_thumb_writer_put_b_imm(self->output, 0x6); - zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); + zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); return TRUE; } // PAGE: A8-334 -zbool zz_thumb_relocator_rewrite_B_T4(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_B_T4(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 insn2 = insn_ctx->insn2; @@ -261,12 +387,13 @@ zbool zz_thumb_relocator_rewrite_B_T4(ZzThumbRelocator *self, const ZzInstructio zaddr target_address; target_address = insn_ctx->pc + imm32; - zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); + zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); return TRUE; } // PAGE: A8-348 -zbool zz_thumb_relocator_rewrite_BLBLX_immediate_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_BLBLX_immediate_T1(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 insn2 = insn_ctx->insn2; @@ -281,18 +408,19 @@ zbool zz_thumb_relocator_rewrite_BLBLX_immediate_T1(ZzThumbRelocator *self, cons imm11 << 1 | imm10 << (1 + 11) | I1 << (1 + 11 + 6) | I2 << (1 + 11 + 6 + 1) | S << (1 + 11 + 6 + 1 + 1); zaddr target_address; + // CurrentInstrSet = thumb + // targetInstrSet = arm target_address = insn_ctx->pc + imm32; - if ((zaddr)insn_ctx->pc % 4) - target_address -= 2; - zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, - (insn_ctx->type == THUMB2_INSN) ? insn_ctx->pc : (insn_ctx->pc - 2)); + ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); + zz_thumb_writer_put_ldr_b_reg_relocate_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 1, literal_insn_ptr); zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); return TRUE; } // PAGE: A8-348 -zbool zz_thumb_relocator_rewrite_BLBLX_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx) { +zbool zz_thumb_relocator_rewrite_BLBLX_T2(ZzThumbRelocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn1 = insn_ctx->insn1; zuint32 insn2 = insn_ctx->insn2; @@ -308,59 +436,70 @@ zbool zz_thumb_relocator_rewrite_BLBLX_T2(ZzThumbRelocator *self, const ZzInstru zuint32 imm32 = imm10_2 << 2 | imm10_1 << (2 + 10) | I1 << (2 + 10 + 6) | I2 << (2 + 10 + 6 + 1) | S << (2 + 10 + 6 + 1 + 1); zaddr target_address; - target_address = insn_ctx->pc + imm32; - zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc); - zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); + // CurrentInstrSet = thumb + // targetInstrSet = arm + target_address = ALIGN_4(insn_ctx->pc) + imm32; + + ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); + zz_thumb_writer_put_ldr_b_reg_relocate_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc + 1, literal_insn_ptr); + zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); return TRUE; } zbool zz_thumb_relocator_write_one(ZzThumbRelocator *self) { const ZzInstruction *insn_ctx; + ZzRelocateInstruction *re_insn_ctx; zbool rewritten = FALSE; if (self->inpos != self->outpos) { insn_ctx = &self->input_insns[self->outpos]; + re_insn_ctx = &self->output_insns[self->outpos]; self->outpos++; } else return FALSE; + re_insn_ctx->relocated_offset = (zaddr)self->output->pc - (zaddr)self->output->base; + switch (GetTHUMBInsnType(insn_ctx->insn1, insn_ctx->insn2)) { + case THUMB_INS_CBNZ_CBZ: + rewritten = zz_thumb_relocator_rewrite_CBNZ_CBZ(self, insn_ctx, re_insn_ctx); + break; case THUMB_INS_ADD_register_T2: - rewritten = zz_thumb_relocator_rewrite_ADD_register_T2(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_ADD_register_T2(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_LDR_literal_T1: - rewritten = zz_thumb_relocator_rewrite_LDR_literal_T1(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_LDR_literal_T1(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_LDR_literal_T2: - rewritten = zz_thumb_relocator_rewrite_LDR_literal_T2(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_LDR_literal_T2(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_ADR_T1: - rewritten = zz_thumb_relocator_rewrite_ADR_T1(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_ADR_T1(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_ADR_T2: - rewritten = zz_thumb_relocator_rewrite_ADR_T2(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_ADR_T2(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_ADR_T3: - rewritten = zz_thumb_relocator_rewrite_ADR_T3(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_ADR_T3(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_B_T1: - rewritten = zz_thumb_relocator_rewrite_B_T1(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_B_T1(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_B_T2: - rewritten = zz_thumb_relocator_rewrite_B_T2(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_B_T2(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_B_T3: - rewritten = zz_thumb_relocator_rewrite_B_T3(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_B_T3(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_B_T4: - rewritten = zz_thumb_relocator_rewrite_B_T4(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_B_T4(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_BLBLX_immediate_T1: - rewritten = zz_thumb_relocator_rewrite_BLBLX_immediate_T1(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_BLBLX_immediate_T1(self, insn_ctx, re_insn_ctx); break; case THUMB_INS_BLBLX_immediate_T2: - rewritten = zz_thumb_relocator_rewrite_BLBLX_T2(self, insn_ctx); + rewritten = zz_thumb_relocator_rewrite_BLBLX_T2(self, insn_ctx, re_insn_ctx); break; case THUMB_UNDEF: rewritten = FALSE; @@ -368,5 +507,9 @@ zbool zz_thumb_relocator_write_one(ZzThumbRelocator *self) { } if (!rewritten) zz_thumb_writer_put_bytes(self->output, (zbyte *)&insn_ctx->insn, insn_ctx->size); + + re_insn_ctx->relocated_length = + (zaddr)self->output->pc - (zaddr)self->output->base - (zaddr)re_insn_ctx->relocated_offset; + return TRUE; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.h index 679bbd2f4..1baeac0eb 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.h @@ -32,12 +32,16 @@ #include "zzdeps/zz.h" typedef struct _ZzThumbRelocator { + zbool try_relocated_again; + zsize try_relocated_length; zpointer input_start; zpointer input_cur; zaddr input_pc; ZzInstruction *input_insns; + ZzRelocateInstruction *output_insns; + ZzLiteralInstruction **relocate_literal_insns; + zsize relocate_literal_insns_size; ZzThumbWriter *output; - zuint inpos; zuint outpos; } ZzThumbRelocator; @@ -46,12 +50,8 @@ void zz_thumb_relocator_init(ZzThumbRelocator *relocator, zpointer input_code, Z void zz_thumb_relocator_reset(ZzThumbRelocator *self, zpointer input_code, ZzThumbWriter *output); zsize zz_thumb_relocator_read_one(ZzThumbRelocator *self, ZzInstruction *instruction); zbool zz_thumb_relocator_write_one(ZzThumbRelocator *self); +void zz_thumb_relocator_relocate_writer(ZzThumbRelocator *relocator, zaddr code_address); void zz_thumb_relocator_write_all(ZzThumbRelocator *self); void zz_thumb_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes); -zbool zz_thumb_relocator_rewrite_ldr(ZzThumbRelocator *self, ZzInstruction *insn_ctx); -zbool zz_thumb_relocator_rewrite_add(ZzThumbRelocator *self, ZzInstruction *insn_ctx); -zbool zz_thumb_relocator_rewrite_b(ZzThumbRelocator *self, ZzInstruction *insn_ctx); -zbool zz_thumb_relocator_rewrite_b_cond(ZzThumbRelocator *self, ZzInstruction *insn_ctx); -zbool zz_thumb_relocator_rewrite_bl(ZzThumbRelocator *self, ZzInstruction *insn_ctx); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c index a54aabb9a..1e43a6a20 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c @@ -28,7 +28,7 @@ ZzArmWriter *zz_arm_writer_new(zpointer data_ptr) { writer->codedata = data_ptr + t; writer->base = data_ptr + t; - writer->pc = data_ptr + t; + writer->pc = (zaddr)data_ptr + t; writer->size = 0; return writer; } @@ -38,21 +38,45 @@ void zz_arm_writer_init(ZzArmWriter *self, zpointer data_ptr) { zz_arm_writer_re void zz_arm_writer_reset(ZzArmWriter *self, zpointer data_ptr) { int t = (zaddr)data_ptr % 4; + ZzArmWriter tmp = {0}; + *self = tmp; + self->codedata = data_ptr + t; self->base = data_ptr + t; - self->pc = data_ptr + t + 8; + self->pc = (zaddr)data_ptr + t; self->size = 0; } zsize zz_arm_writer_near_jump_range_size() { return ((1 << 23) << 2); } +// ------- relocator ------- + +ZzLiteralInstruction *zz_arm_writer_put_ldr_b_reg_relocate_address(ZzArmWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr) { + zz_arm_writer_put_ldr_b_reg_address(self, reg, address); + ZzLiteralInstruction *literal_insn = &(self->literal_insns[self->literal_insn_size - 1]); + *literal_insn_ptr = literal_insn; + return literal_insn; +} + +ZzLiteralInstruction *zz_arm_writer_put_ldr_reg_relocate_address(ZzArmWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr) { + zz_arm_writer_put_ldr_reg_address(self, reg, address); + ZzLiteralInstruction *literal_insn = &(self->literal_insns[self->literal_insn_size - 1]); + *literal_insn_ptr = literal_insn; + return literal_insn; +} + // ------- user custom ------- void zz_arm_writer_put_ldr_b_reg_address(ZzArmWriter *self, ZzARMReg reg, zaddr address) { + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; zz_arm_writer_put_ldr_reg_reg_imm(self, reg, ZZ_ARM_REG_PC, 0); zz_arm_writer_put_b_imm(self, 0x0); + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_arm_writer_put_bytes(self, (zpointer)&address, sizeof(zpointer)); } + void zz_arm_writer_put_bx_to_thumb(ZzArmWriter *self) { zz_arm_writer_put_sub_reg_reg_imm(self, ZZ_ARM_REG_SP, ZZ_ARM_REG_SP, 0x8); zz_arm_writer_put_str_reg_reg_imm(self, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); @@ -150,8 +174,11 @@ void zz_arm_writer_put_str_reg_reg_imm(ZzArmWriter *self, ZzARMReg dst_reg, ZzAR zz_arm_writer_put_instruction(self, 0xe4000000 | rd.index << 12 | rs.index << 16 | P << 24 | U << 23 | W << 21 | (imm & ZZ_INT12_MASK)); } + void zz_arm_writer_put_ldr_reg_address(ZzArmWriter *self, ZzARMReg reg, zaddr address) { + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; zz_arm_writer_put_ldr_reg_reg_imm(self, reg, ZZ_ARM_REG_PC, -4); + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_arm_writer_put_bytes(self, (zpointer)&address, sizeof(zpointer)); } @@ -181,17 +208,17 @@ void zz_arm_writer_put_bx_reg(ZzArmWriter *self, ZzARMReg reg) { void zz_arm_writer_put_nop(ZzArmWriter *self) { zz_arm_writer_put_instruction(self, 0xe320f000); } -zpointer zz_arm_writer_put_push_reg(ZzArmWriter *self, ZzARMReg reg) { +void zz_arm_writer_put_push_reg(ZzArmWriter *self, ZzARMReg reg) { ZzArmRegInfo ri; zz_arm_register_describe(reg, &ri); zz_arm_writer_put_instruction(self, 0b11100101001011010000000000000100 | ri.index << 12); - return self->pc; + return; } -zpointer zz_arm_writer_put_pop_reg(ZzArmWriter *self, ZzARMReg reg) { +void zz_arm_writer_put_pop_reg(ZzArmWriter *self, ZzARMReg reg) { ZzArmRegInfo ri; zz_arm_register_describe(reg, &ri); zz_arm_writer_put_instruction(self, 0b11100100100111010000000000000100 | ri.index << 12); - return self->pc; + return; } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h index 37694e3b9..95826608c 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.h @@ -62,7 +62,10 @@ void zz_arm_writer_put_ldr_reg_reg_imm_A1(ZzArmWriter *self, ZzARMReg dst_reg, Z void zz_arm_writer_put_ldr_reg_address(ZzArmWriter *self, ZzARMReg reg, zaddr address); void zz_arm_writer_put_add_reg_reg_imm(ZzArmWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, zuint32 imm); void zz_arm_writer_put_sub_reg_reg_imm(ZzArmWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, zuint32 imm); -zpointer zz_arm_writer_put_push_reg(ZzArmWriter *self, ZzARMReg reg); -zpointer zz_arm_writer_put_pop_reg(ZzArmWriter *self, ZzARMReg reg); - +void zz_arm_writer_put_push_reg(ZzArmWriter *self, ZzARMReg reg); +void zz_arm_writer_put_pop_reg(ZzArmWriter *self, ZzARMReg reg); +ZzLiteralInstruction *zz_arm_writer_put_ldr_b_reg_relocate_address(ZzArmWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr); +ZzLiteralInstruction *zz_arm_writer_put_ldr_reg_relocate_address(ZzArmWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c index 8a5654275..f77d86a50 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c @@ -28,7 +28,7 @@ ZzThumbWriter *zz_thumb_writer_new(zpointer data_ptr) { writer->codedata = data_ptr + t; writer->base = data_ptr + t; - writer->pc = data_ptr + t; + writer->pc = (zaddr)data_ptr + t; writer->size = 0; return writer; } @@ -38,17 +38,41 @@ void zz_thumb_writer_init(ZzThumbWriter *self, zpointer data_ptr) { zz_thumb_wri void zz_thumb_writer_reset(ZzThumbWriter *self, zpointer data_ptr) { int t = (zaddr)data_ptr % 4; + ZzThumbWriter tmp = {0}; + *self = tmp; + self->codedata = data_ptr + t; self->base = data_ptr + t; - self->pc = data_ptr + t + 4; + self->pc = (zaddr)data_ptr + t; self->size = 0; } zsize zz_thumb_writer_near_jump_range_size() { return ((1 << 23) << 1); } -zpointer zz_thumb_writer_put_ldr_b_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address) { +// ------- relocator ------- + +ZzLiteralInstruction *zz_thumb_writer_put_ldr_b_reg_relocate_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr) { + zz_thumb_writer_put_ldr_b_reg_address(self, reg, address); + ZzLiteralInstruction *literal_insn = &(self->literal_insns[self->literal_insn_size - 1]); + *literal_insn_ptr = literal_insn; + return literal_insn; +} + +ZzLiteralInstruction *zz_thumb_writer_put_ldr_reg_relocate_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr) { + zz_thumb_writer_put_ldr_reg_address(self, reg, address); + ZzLiteralInstruction *literal_insn = &(self->literal_insns[self->literal_insn_size - 1]); + *literal_insn_ptr = literal_insn; + return literal_insn; +} + +// ------- custom ------- + +void zz_thumb_writer_put_ldr_b_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address) { ZzArmRegInfo ri; zz_arm_register_describe(reg, &ri); + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; if ((((zaddr)self->pc) % 4)) { if (ri.meta <= ZZ_ARM_REG_R7) { @@ -67,14 +91,17 @@ zpointer zz_thumb_writer_put_ldr_b_reg_address(ZzThumbWriter *self, ZzARMReg reg } zz_thumb_writer_put_b_imm(self, 0x2); + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_thumb_writer_put_bytes(self, (zpointer)&address, sizeof(zpointer)); - return self->pc; + return; } -zpointer zz_thumb_writer_put_ldr_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address) { +void zz_thumb_writer_put_ldr_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address) { ZzArmRegInfo ri; zz_arm_register_describe(reg, &ri); + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; + if ((((zaddr)self->pc) % 4)) { if (ri.meta <= ZZ_ARM_REG_R7) { zz_thumb_writer_put_ldr_reg_imm(self, reg, 0x0); @@ -88,40 +115,40 @@ zpointer zz_thumb_writer_put_ldr_reg_address(ZzThumbWriter *self, ZzARMReg reg, zz_thumb_writer_put_nop(self); } + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_thumb_writer_put_bytes(self, (zpointer)&address, sizeof(zpointer)); - return self->pc; + return; } -// ------- user custom ------- // ------- architecture default ------- -zpointer zz_thumb_writer_put_nop(ZzThumbWriter *self) { +void zz_thumb_writer_put_nop(ZzThumbWriter *self) { zz_thumb_writer_put_instruction(self, 0x46c0); - return self->pc; + return; } -zpointer zz_thumb_writer_put_bytes(ZzThumbWriter *self, zbyte *data, zuint data_size) { +void zz_thumb_writer_put_bytes(ZzThumbWriter *self, zbyte *data, zuint data_size) { memcpy(self->codedata, data, data_size); self->codedata = (zpointer)self->codedata + data_size; self->pc += data_size; self->size += data_size; - return self->pc; + return; } -zpointer zz_thumb_writer_put_instruction(ZzThumbWriter *self, uint16_t insn) { +void zz_thumb_writer_put_instruction(ZzThumbWriter *self, uint16_t insn) { *(uint16_t *)(self->codedata) = insn; self->codedata = (zpointer)self->codedata + sizeof(uint16_t); self->pc += 2; self->size += 2; - return self->pc; + return; } -zpointer zz_thumb_writer_put_b_imm(ZzThumbWriter *self, zuint32 imm) { +void zz_thumb_writer_put_b_imm(ZzThumbWriter *self, zuint32 imm) { zz_thumb_writer_put_instruction(self, 0xe000 | ((imm / 2) & ZZ_INT11_MASK)); - return self->pc; + return; } -zpointer zz_thumb_writer_put_bx_reg(ZzThumbWriter *self, ZzARMReg reg) { +void zz_thumb_writer_put_bx_reg(ZzThumbWriter *self, ZzARMReg reg) { ZzArmRegInfo ri; zz_arm_register_describe(reg, &ri); @@ -132,20 +159,20 @@ zpointer zz_thumb_writer_put_bx_reg(ZzThumbWriter *self, ZzARMReg reg) { zz_thumb_writer_put_instruction(self, 0x4700 | (ri.index << 3)); zz_thumb_writer_put_nop(self); - return self->pc; + return; } -zpointer zz_thumb_writer_put_blx_reg(ZzThumbWriter *self, ZzARMReg reg) { +void zz_thumb_writer_put_blx_reg(ZzThumbWriter *self, ZzARMReg reg) { ZzArmRegInfo ri; zz_arm_register_describe(reg, &ri); zz_thumb_writer_put_instruction(self, 0x4780 | (ri.index << 3)); - return self->pc; + return; } // A8.8.18 -zpointer zz_thumb_writer_put_branch_imm(ZzThumbWriter *self, zuint32 imm, zbool link, zbool thumb) { +void zz_thumb_writer_put_branch_imm(ZzThumbWriter *self, zuint32 imm, zbool link, zbool thumb) { union { zint32 i; zuint32 u; @@ -163,27 +190,27 @@ zpointer zz_thumb_writer_put_branch_imm(ZzThumbWriter *self, zuint32 imm, zbool zz_thumb_writer_put_instruction(self, 0xf000 | (s << 10) | imm10); zz_thumb_writer_put_instruction(self, 0x8000 | (link << 14) | (j1 << 13) | (thumb << 12) | (j2 << 11) | imm11); - return self->pc; + return; } -zpointer zz_thumb_writer_put_bl_imm(ZzThumbWriter *self, zuint32 imm) { +void zz_thumb_writer_put_bl_imm(ZzThumbWriter *self, zuint32 imm) { zz_thumb_writer_put_branch_imm(self, imm, TRUE, TRUE); - return self->pc; + return; } -zpointer zz_thumb_writer_put_blx_imm(ZzThumbWriter *self, zuint32 imm) { +void zz_thumb_writer_put_blx_imm(ZzThumbWriter *self, zuint32 imm) { zz_thumb_writer_put_branch_imm(self, imm, TRUE, FALSE); - return self->pc; + return; } -zpointer zz_thumb_writer_put_b_imm32(ZzThumbWriter *self, zuint32 imm) { +void zz_thumb_writer_put_b_imm32(ZzThumbWriter *self, zuint32 imm) { zz_thumb_writer_put_branch_imm(self, imm, FALSE, TRUE); - return self->pc; + return; } // PAGE: A8-410 // A8.8.64 LDR (literal) -zpointer zz_thumb_writer_put_ldr_reg_imm(ZzThumbWriter *self, ZzARMReg reg, zint32 imm) { +void zz_thumb_writer_put_ldr_reg_imm(ZzThumbWriter *self, ZzARMReg reg, zint32 imm) { ZzArmRegInfo ri; zz_arm_register_describe(reg, &ri); @@ -198,11 +225,11 @@ zpointer zz_thumb_writer_put_ldr_reg_imm(ZzThumbWriter *self, ZzARMReg reg, zint zz_thumb_writer_put_instruction(self, 0xf85f | (add << 7)); zz_thumb_writer_put_instruction(self, (ri.index << 12) | ABS(imm)); } - return self->pc; + return; } -zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T1(ZzThumbWriter *self, ZzThumbMemoryOperation operation, - ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { +zbool zz_thumb_writer_put_transfer_reg_reg_offset_T1(ZzThumbWriter *self, ZzThumbMemoryOperation operation, + ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { ZzArmRegInfo lr, rr; zz_arm_register_describe(left_reg, &lr); @@ -211,20 +238,20 @@ zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T1(ZzThumbWriter *self, ZzT zuint16 insn; if (right_offset < 0) - return 0; + return FALSE; if (lr.meta <= ZZ_ARM_REG_R7 && rr.meta <= ZZ_ARM_REG_R7 && right_offset < ((1 << 5) << 2)) { insn = 0x6000 | (right_offset / 4) << 6 | (rr.index << 3) | lr.index; if (operation == ZZ_THUMB_MEMORY_LOAD) insn |= 0x0800; zz_thumb_writer_put_instruction(self, insn); - return self->pc; + return TRUE; } - return 0; + return FALSE; } -zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T2(ZzThumbWriter *self, ZzThumbMemoryOperation operation, - ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { +zbool zz_thumb_writer_put_transfer_reg_reg_offset_T2(ZzThumbWriter *self, ZzThumbMemoryOperation operation, + ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { ZzArmRegInfo lr, rr; zz_arm_register_describe(left_reg, &lr); @@ -233,20 +260,20 @@ zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T2(ZzThumbWriter *self, ZzT zuint16 insn; if (right_offset < 0) - return 0; + return FALSE; if (rr.meta == ZZ_ARM_REG_SP && lr.meta <= ZZ_ARM_REG_R7 && right_offset < ((1 << 8) << 2)) { insn = 0x9000 | (lr.index << 8) | (right_offset / 4); if (operation == ZZ_THUMB_MEMORY_LOAD) insn |= 0x0800; zz_thumb_writer_put_instruction(self, insn); - return self->pc; + return TRUE; } - return 0; + return FALSE; } -zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T3(ZzThumbWriter *self, ZzThumbMemoryOperation operation, - ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { +zbool zz_thumb_writer_put_transfer_reg_reg_offset_T3(ZzThumbWriter *self, ZzThumbMemoryOperation operation, + ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { ZzArmRegInfo lr, rr; zz_arm_register_describe(left_reg, &lr); @@ -255,7 +282,7 @@ zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T3(ZzThumbWriter *self, ZzT zuint16 insn; if (right_offset < 0) - return 0; + return FALSE; if (right_offset < (1 << 12)) { // if (operation == ZZ_THUMB_MEMORY_LOAD && rr.meta == ZZ_ARM_REG_PC && @@ -269,14 +296,14 @@ zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T3(ZzThumbWriter *self, ZzT 0xf8c0 | ((operation == ZZ_THUMB_MEMORY_LOAD) ? 0x0010 : 0x0000) | rr.index); zz_thumb_writer_put_instruction(self, (lr.index << 12) | right_offset); - return self->pc; + return TRUE; } - return 0; + return FALSE; } -zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T4(ZzThumbWriter *self, ZzThumbMemoryOperation operation, - ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset, - zbool index, zbool wback) { +zbool zz_thumb_writer_put_transfer_reg_reg_offset_T4(ZzThumbWriter *self, ZzThumbMemoryOperation operation, + ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset, + zbool index, zbool wback) { ZzArmRegInfo lr, rr; zz_arm_register_describe(left_reg, &lr); @@ -295,65 +322,64 @@ zpointer zz_thumb_writer_put_transfer_reg_reg_offset_T4(ZzThumbWriter *self, ZzT rr.index); zz_thumb_writer_put_instruction(self, 0x0800 | (lr.index << 12) | (index << 10) | (add << 9) | (wback << 8) | (ABS(right_offset))); - return self->pc; + return TRUE; } } - return 0; + return FALSE; } // PAGE: A8-406 // PAGE: A8.8.203 STR (immediate, Thumb) -static zpointer zz_thumb_writer_put_transfer_reg_reg_offset(ZzThumbWriter *self, ZzThumbMemoryOperation operation, - ZzARMReg left_reg, ZzARMReg right_reg, - zint32 right_offset) { +static void zz_thumb_writer_put_transfer_reg_reg_offset(ZzThumbWriter *self, ZzThumbMemoryOperation operation, + ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset) { if (zz_thumb_writer_put_transfer_reg_reg_offset_T1(self, operation, left_reg, right_reg, right_offset)) - return self->pc; + return; if (zz_thumb_writer_put_transfer_reg_reg_offset_T2(self, operation, left_reg, right_reg, right_offset)) - return self->pc; + return; if (zz_thumb_writer_put_transfer_reg_reg_offset_T3(self, operation, left_reg, right_reg, right_offset)) - return self->pc; + return; if (zz_thumb_writer_put_transfer_reg_reg_offset_T4(self, operation, left_reg, right_reg, right_offset, 1, 0)) - return self->pc; - return 0; + return; + return; } -zpointer zz_thumb_writer_put_ldr_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, - zint32 src_offset) { +void zz_thumb_writer_put_ldr_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, + zint32 src_offset) { zz_thumb_writer_put_transfer_reg_reg_offset(self, ZZ_THUMB_MEMORY_LOAD, dst_reg, src_reg, src_offset); - return self->pc; + return; } -zpointer zz_thumb_writer_put_str_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, - zint32 dst_offset) { +void zz_thumb_writer_put_str_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, + zint32 dst_offset) { zz_thumb_writer_put_transfer_reg_reg_offset(self, ZZ_THUMB_MEMORY_STORE, src_reg, dst_reg, dst_offset); - return self->pc; + return; } -zpointer zz_thumb_writer_put_ldr_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, - zint32 src_offset, zbool index) { +void zz_thumb_writer_put_ldr_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, + zint32 src_offset, zbool index) { zz_thumb_writer_put_transfer_reg_reg_offset_T4(self, ZZ_THUMB_MEMORY_LOAD, dst_reg, src_reg, src_offset, index, 1); - return self->pc; + return; } -zpointer zz_thumb_writer_put_str_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, - zint32 dst_offset, zbool index) { +void zz_thumb_writer_put_str_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, + zint32 dst_offset, zbool index) { zz_thumb_writer_put_transfer_reg_reg_offset_T4(self, ZZ_THUMB_MEMORY_STORE, src_reg, dst_reg, dst_offset, index, 1); - return self->pc; + return; } -zpointer zz_thumb_writer_put_str_reg_reg(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg) { +void zz_thumb_writer_put_str_reg_reg(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg) { zz_thumb_writer_put_str_reg_reg_offset(self, src_reg, dst_reg, 0); - return self->pc; + return; } -zpointer zz_thumb_writer_put_ldr_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg) { +void zz_thumb_writer_put_ldr_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg) { zz_thumb_writer_put_ldr_reg_reg_offset(self, dst_reg, src_reg, 0); - return self->pc; + return; } -zpointer zz_thumb_writer_put_add_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm) { +void zz_thumb_writer_put_add_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm) { ZzArmRegInfo dst; zuint16 sign_mask, insn; @@ -374,16 +400,15 @@ zpointer zz_thumb_writer_put_add_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, } zz_thumb_writer_put_instruction(self, insn); - return self->pc; + return; } -zpointer zz_thumb_writer_put_sub_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm) { +void zz_thumb_writer_put_sub_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm) { zz_thumb_writer_put_add_reg_imm(self, dst_reg, -imm); - return self->pc; + return; } -zpointer zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, - zint32 right_value) { +void zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, zint32 right_value) { ZzArmRegInfo dst, left; zuint16 insn; @@ -394,11 +419,17 @@ zpointer zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_r return zz_thumb_writer_put_add_reg_imm(self, dst_reg, right_value); } - if (left.meta == ZZ_ARM_REG_SP || left.meta == ZZ_ARM_REG_PC) { - zuint16 base_mask; + if (dst.meta <= ZZ_ARM_REG_R7 && left.meta <= ZZ_ARM_REG_R7 && ABS(right_value) < (1 << 3)) { + zuint32 sign_mask = 0; - if (right_value < 0 || right_value % 4 != 0) - return 0; + if (right_value < 0) + sign_mask = 1 << 9; + + insn = 0x1c00 | sign_mask | (ABS(right_value) << 6) | (left.index << 3) | dst.index; + zz_thumb_writer_put_instruction(self, insn); + } else if ((left.meta == ZZ_ARM_REG_SP || left.meta == ZZ_ARM_REG_PC) && dst.meta <= ZZ_ARM_REG_R7 && + right_value > 0 && (right_value % 4 != 0) && right_value < (1 << 8)) { + zuint16 base_mask; if (left.meta == ZZ_ARM_REG_SP) base_mask = 0x0800; @@ -406,49 +437,50 @@ zpointer zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_r base_mask = 0x0000; insn = 0xa000 | base_mask | (dst.index << 8) | (right_value / 4); + zz_thumb_writer_put_instruction(self, insn); } else { - zuint16 sign_mask = 0x0000; - - if (ABS(right_value) > 7) - return 0; - + zuint16 insn1, insn2; + zuint i, imm3, imm8; + i = (ABS(right_value) >> (3 + 8)) & 0x1; + imm3 = (ABS(right_value) >> 8) & 0b111; + imm8 = ABS(right_value) & 0b11111111; + + // A8-708, sub + // A8-306 add if (right_value < 0) - sign_mask = 0x0200; - - insn = 0x1c00 | sign_mask | (ABS(right_value) << 6) | (left.index << 3) | dst.index; + zz_thumb_writer_put_instruction(self, 0b1111001010100000 | i << 10 | left.index); + else + zz_thumb_writer_put_instruction(self, 0b1111001000000000 | i << 10 | left.index); + zz_thumb_writer_put_instruction(self, 0b0 | imm3 << 12 | dst.index << 8 | imm8); } - zz_thumb_writer_put_instruction(self, insn); - - return self->pc; + return; } -zpointer zz_thumb_writer_put_sub_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, - zint32 right_value) { +void zz_thumb_writer_put_sub_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, zint32 right_value) { zz_thumb_writer_put_add_reg_reg_imm(self, dst_reg, left_reg, -right_value); - return self->pc; + return; } -zpointer zz_thumb_writer_put_push_reg(ZzThumbWriter *self, zint32 regs) { +void zz_thumb_writer_put_push_reg(ZzThumbWriter *self, zint32 regs) { zuint16 M, register_list; M = 0; register_list = regs & 0xFF; zz_thumb_writer_put_instruction(self, 0b1011010000000000 | M << 8 | register_list); - return self->pc; + return; } -zpointer zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs) { +void zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs) { zuint16 P, register_list; P = 0; register_list = regs & 0xFF; zz_thumb_writer_put_instruction(self, 0b1011110000000000 | P << 8 | register_list); - return self->pc; + return; } -zpointer zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, - ZzARMReg right_reg) { +void zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, ZzARMReg right_reg) { ZzArmRegInfo dst, left, right; zz_arm_register_describe(dst_reg, &dst); zz_arm_register_describe(left_reg, &left); @@ -460,5 +492,5 @@ zpointer zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_r Rn_ndx = left.index; zz_thumb_writer_put_instruction(self, 0b0001100000000000 | Rm_ndx << 6 | Rn_ndx << 3 | Rd_ndx); - return self->pc; + return; } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h index 5a277ba58..53704b9c0 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h @@ -40,7 +40,7 @@ typedef enum _ZzThumbMemoryOperation { ZZ_THUMB_MEMORY_LOAD, ZZ_THUMB_MEMORY_STO // ------- user custom ------- -zpointer zz_thumb_writer_put_ldr_b_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address); +void zz_thumb_writer_put_ldr_b_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address); // ------- architecture default ------- @@ -48,40 +48,39 @@ ZzThumbWriter *zz_thumb_writer_new(zpointer data_ptr); void zz_thumb_writer_init(ZzThumbWriter *self, zpointer data_ptr); void zz_thumb_writer_reset(ZzThumbWriter *self, zpointer data_ptr); zsize zz_thumb_writer_near_jump_range_size(); -zpointer zz_thumb_writer_put_nop(ZzThumbWriter *self); -zpointer zz_thumb_writer_put_bytes(ZzThumbWriter *self, zbyte *data, zuint data_size); -zpointer zz_thumb_writer_put_instruction(ZzThumbWriter *self, uint16_t insn); -zpointer zz_thumb_writer_put_b_imm(ZzThumbWriter *self, zuint32 imm); -zpointer zz_thumb_writer_put_bx_reg(ZzThumbWriter *self, ZzARMReg reg); -zpointer zz_thumb_writer_put_blx_reg(ZzThumbWriter *self, ZzARMReg reg); -zpointer zz_thumb_writer_put_branch_imm(ZzThumbWriter *self, zuint32 imm, zbool link, zbool thumb); -zpointer zz_thumb_writer_put_bl_imm(ZzThumbWriter *self, zuint32 imm); -zpointer zz_thumb_writer_put_blx_imm(ZzThumbWriter *self, zuint32 imm); -zpointer zz_thumb_writer_put_b_imm32(ZzThumbWriter *self, zuint32 imm); +void zz_thumb_writer_put_nop(ZzThumbWriter *self); +void zz_thumb_writer_put_bytes(ZzThumbWriter *self, zbyte *data, zuint data_size); +void zz_thumb_writer_put_instruction(ZzThumbWriter *self, uint16_t insn); +void zz_thumb_writer_put_b_imm(ZzThumbWriter *self, zuint32 imm); +void zz_thumb_writer_put_bx_reg(ZzThumbWriter *self, ZzARMReg reg); +void zz_thumb_writer_put_blx_reg(ZzThumbWriter *self, ZzARMReg reg); +void zz_thumb_writer_put_branch_imm(ZzThumbWriter *self, zuint32 imm, zbool link, zbool thumb); +void zz_thumb_writer_put_bl_imm(ZzThumbWriter *self, zuint32 imm); +void zz_thumb_writer_put_blx_imm(ZzThumbWriter *self, zuint32 imm); +void zz_thumb_writer_put_b_imm32(ZzThumbWriter *self, zuint32 imm); -zpointer zz_thumb_writer_put_ldr_reg_imm(ZzThumbWriter *self, ZzARMReg reg, zint32 imm); -zpointer zz_thumb_writer_put_ldr_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address); +void zz_thumb_writer_put_ldr_reg_imm(ZzThumbWriter *self, ZzARMReg reg, zint32 imm); +void zz_thumb_writer_put_ldr_reg_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address); -static zpointer zz_thumb_writer_put_transfer_reg_reg_offset(ZzThumbWriter *self, ZzThumbMemoryOperation operation, - ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset); -zpointer zz_thumb_writer_put_ldr_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, - zint32 src_offset); -zpointer zz_thumb_writer_put_str_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, - zint32 dst_offset); -zpointer zz_thumb_writer_put_str_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, - zint32 dst_offset, zbool index); -zpointer zz_thumb_writer_put_ldr_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, - zint32 src_offset, zbool index); -zpointer zz_thumb_writer_put_str_reg_reg(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg); -zpointer zz_thumb_writer_put_ldr_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg); -zpointer zz_thumb_writer_put_add_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm); -zpointer zz_thumb_writer_put_sub_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm); -zpointer zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, - zint32 right_value); -zpointer zz_thumb_writer_put_sub_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, - zint32 right_value); -zpointer zz_thumb_writer_put_push_reg(ZzThumbWriter *self, zint32 regs); -zpointer zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs); -zpointer zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, - ZzARMReg right_reg); +static void zz_thumb_writer_put_transfer_reg_reg_offset(ZzThumbWriter *self, ZzThumbMemoryOperation operation, + ZzARMReg left_reg, ZzARMReg right_reg, zint32 right_offset); +void zz_thumb_writer_put_ldr_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, zint32 src_offset); +void zz_thumb_writer_put_str_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, zint32 dst_offset); +void zz_thumb_writer_put_str_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg, + zint32 dst_offset, zbool index); +void zz_thumb_writer_put_ldr_index_reg_reg_offset(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg, + zint32 src_offset, zbool index); +void zz_thumb_writer_put_str_reg_reg(ZzThumbWriter *self, ZzARMReg src_reg, ZzARMReg dst_reg); +void zz_thumb_writer_put_ldr_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg src_reg); +void zz_thumb_writer_put_add_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm); +void zz_thumb_writer_put_sub_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm); +void zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, zint32 right_value); +void zz_thumb_writer_put_sub_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, zint32 right_value); +void zz_thumb_writer_put_push_reg(ZzThumbWriter *self, zint32 regs); +void zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs); +void zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, ZzARMReg right_reg); +ZzLiteralInstruction *zz_thumb_writer_put_ldr_reg_relocate_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr); +ZzLiteralInstruction *zz_thumb_writer_put_ldr_b_reg_relocate_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.c index e192e9055..00ec11d1c 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.c @@ -6,7 +6,8 @@ zuint32 get_insn_sub(zuint32 insn, int start, int length) { return (insn >> star zbool insn_equal(zuint32 insn, char *opstr) { zuint32 mask = 0, value = 0; zsize length = strlen(opstr); - for (int i = length - 1, j = 0; i >= 0 && j < length; i--, j++) { + int i, j; + for (i = length - 1, j = 0; i >= 0 && j < length; i--, j++) { if (opstr[i] == 'x') { mask = mask | (0 << j); } else if (opstr[i] == '0') { diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.h index 78948cdcf..d16d377c5 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/instructions.h @@ -26,6 +26,12 @@ typedef struct _ZzInstruction { zuint32 insn; } ZzInstruction; +typedef struct _ZzRelocateInstruction { + const ZzInstruction *insn_ctx; + zaddr relocated_offset; + zsize relocated_length; +} ZzRelocateInstruction; + zuint32 get_insn_sub(zuint32 insn, int start, int length); zbool insn_equal(zuint32 insn, char *opstr); diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c index eb4a49a6f..9f8f99b4d 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c @@ -23,31 +23,43 @@ void zz_arm64_relocator_init(ZzArm64Relocator *relocator, zpointer input_code, ZzArm64Writer *output) { relocator->inpos = 0; relocator->outpos = 0; - + relocator->output = output; relocator->input_start = input_code; relocator->input_cur = input_code; relocator->input_pc = (zaddr)input_code; - relocator->input_insns = (ZzInstruction *)malloc(MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); + relocator->relocate_literal_insns_size = 0; + relocator->try_relocated_length = 0; + relocator->input_insns = (ZzInstruction *)malloc(MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); memset(relocator->input_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); - - relocator->output = output; + relocator->output_insns = + (ZzRelocateInstruction *)malloc(MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + memset(relocator->output_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + relocator->relocate_literal_insns = + (ZzLiteralInstruction **)malloc(MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); + memset(relocator->relocate_literal_insns, 0, MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); } void zz_arm64_relocator_reset(ZzArm64Relocator *self, zpointer input_code, ZzArm64Writer *output) { self->input_cur = input_code; self->input_start = input_code; self->input_pc = (zaddr)input_code; - self->inpos = 0; self->outpos = 0; - self->output = output; + self->relocate_literal_insns_size = 0; + self->try_relocated_length = 0; + + memset(self->input_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzInstruction)); + memset(self->output_insns, 0, MAX_RELOCATOR_INSTRUCIONS_SIZE * sizeof(ZzRelocateInstruction)); + memset(self->relocate_literal_insns, 0, MAX_LITERAL_INSN_SIZE * sizeof(ZzLiteralInstruction *)); } zsize zz_arm64_relocator_read_one(ZzArm64Relocator *self, ZzInstruction *instruction) { ZzInstruction *insn_ctx = &self->input_insns[self->inpos]; + ZzRelocateInstruction *re_insn_ctx = &self->output_insns[self->inpos]; + re_insn_ctx->insn_ctx = insn_ctx; zz_arm64_reader_read_one_instruction(insn_ctx, self->input_cur); // switch (0) {} @@ -63,19 +75,76 @@ zsize zz_arm64_relocator_read_one(ZzArm64Relocator *self, ZzInstruction *instruc return self->input_cur - self->input_start; } +zaddr zz_arm64_relocator_get_insn_relocated_offset(ZzArm64Relocator *self, zaddr address) { + const ZzInstruction *insn_ctx; + const ZzRelocateInstruction *re_insn_ctx; + int i; + for (i = 0; i < self->inpos; i++) { + re_insn_ctx = &self->output_insns[i]; + insn_ctx = re_insn_ctx->insn_ctx; + if (insn_ctx->address == address && re_insn_ctx->relocated_offset) { + return re_insn_ctx->relocated_offset; + } + } + return 0; +} + +void zz_arm64_relocator_relocate_writer(ZzArm64Relocator *relocator, zaddr code_address) { + ZzArm64Writer *arm64_writer; + arm64_writer = relocator->output; + if (relocator->relocate_literal_insns_size) { + int i; + zaddr *rebase_ptr; + zaddr literal_address, relocated_offset, relocated_address, *literal_address_ptr; + for (i = 0; i < relocator->relocate_literal_insns_size; i++) { + literal_address_ptr = relocator->relocate_literal_insns[i]->literal_address_ptr; + literal_address = *literal_address_ptr; + relocated_offset = zz_arm64_relocator_get_insn_relocated_offset(relocator, literal_address); + if (relocated_offset) { + relocated_address = code_address + relocated_offset; + *literal_address_ptr = relocated_address; + } + } + } +} + void zz_arm64_relocator_write_all(ZzArm64Relocator *self) { zuint count = 0; + zuint outpos = self->outpos; + ZzArm64Writer arm64_writer = *self->output; + while (zz_arm64_relocator_write_one(self)) count++; } void zz_arm64_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes) { - *max_bytes = 16; + int tmp_size = 0; + zpointer target_addr; + ZzInstruction insn_ctx; + zbool early_end = FALSE; + target_addr = (zpointer)address; + + do { + zz_arm64_reader_read_one_instruction(&insn_ctx, target_addr); + switch (GetARM64InsnType(insn_ctx.insn)) { + case ARM64_INS_B: + early_end = TRUE; + break; + default:; + } + tmp_size += insn_ctx.size; + target_addr = target_addr + insn_ctx.size; + } while (tmp_size < min_bytes); + + if (early_end) { + *max_bytes = tmp_size; + } return; } // PAGE: C6-673 -static zbool zz_arm64_relocator_rewrite_LDR_literal(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm64_relocator_rewrite_LDR_literal(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; // TODO: check opc == 10, with signed zuint32 imm19 = get_insn_sub(insn, 5, 19); @@ -91,7 +160,8 @@ static zbool zz_arm64_relocator_rewrite_LDR_literal(ZzArm64Relocator *self, cons } // PAGE: C6-535 -static zbool zz_arm64_relocator_rewrite_ADR(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm64_relocator_rewrite_ADR(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 immhi = get_insn_sub(insn, 5, 19); zuint32 immlo = get_insn_sub(insn, 29, 2); @@ -106,7 +176,8 @@ static zbool zz_arm64_relocator_rewrite_ADR(ZzArm64Relocator *self, const ZzInst } // PAGE: C6-536 -static zbool zz_arm64_relocator_rewrite_ADRP(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm64_relocator_rewrite_ADRP(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 immhi = get_insn_sub(insn, 5, 19); zuint32 immlo = get_insn_sub(insn, 29, 2); @@ -122,7 +193,8 @@ static zbool zz_arm64_relocator_rewrite_ADRP(ZzArm64Relocator *self, const ZzIns } // PAGE: C6-550 -static zbool zz_arm64_relocator_rewrite_B(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm64_relocator_rewrite_B(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm26 = get_insn_sub(insn, 0, 26); @@ -133,11 +205,13 @@ static zbool zz_arm64_relocator_rewrite_B(ZzArm64Relocator *self, const ZzInstru int Rt_ndx = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_ldr_br_reg_address(self->output, ZZ_ARM64_REG_X17, target_address); + return TRUE; } // PAGE: C6-560 -static zbool zz_arm64_relocator_rewrite_BL(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm64_relocator_rewrite_BL(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm26 = get_insn_sub(insn, 0, 26); @@ -148,6 +222,9 @@ static zbool zz_arm64_relocator_rewrite_BL(ZzArm64Relocator *self, const ZzInstr int Rt_ndx = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_ldr_blr_b_reg_address(self->output, ZZ_ARM64_REG_X17, target_address); + ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); + zz_arm64_writer_put_ldr_br_reg_relocate_address(self->output, ZZ_ARM64_REG_X17, insn_ctx->pc + 4, literal_insn_ptr); + return TRUE; } @@ -163,7 +240,8 @@ static zbool zz_arm64_relocator_rewrite_BL(ZzArm64Relocator *self, const ZzInstr // 0x018 : remain code // PAGE: C6-549 -static zbool zz_arm64_relocator_rewrite_B_cond(ZzArm64Relocator *self, const ZzInstruction *insn_ctx) { +static zbool zz_arm64_relocator_rewrite_B_cond(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx) { zuint32 insn = insn_ctx->insn; zuint32 imm19 = get_insn_sub(insn, 5, 19); @@ -183,32 +261,37 @@ static zbool zz_arm64_relocator_rewrite_B_cond(ZzArm64Relocator *self, const ZzI zbool zz_arm64_relocator_write_one(ZzArm64Relocator *self) { const ZzInstruction *insn_ctx; + ZzRelocateInstruction *re_insn_ctx; + zbool rewritten = FALSE; if (self->inpos != self->outpos) { insn_ctx = &self->input_insns[self->outpos]; + re_insn_ctx = &self->output_insns[self->outpos]; self->outpos++; } else return FALSE; + re_insn_ctx->relocated_offset = (zaddr)self->output->pc - (zaddr)self->output->base; + switch (GetARM64InsnType(insn_ctx->insn)) { case ARM64_INS_LDR_literal: - rewritten = zz_arm64_relocator_rewrite_LDR_literal(self, insn_ctx); + rewritten = zz_arm64_relocator_rewrite_LDR_literal(self, insn_ctx, re_insn_ctx); break; case ARM64_INS_ADR: - rewritten = zz_arm64_relocator_rewrite_ADR(self, insn_ctx); + rewritten = zz_arm64_relocator_rewrite_ADR(self, insn_ctx, re_insn_ctx); break; case ARM64_INS_ADRP: - rewritten = zz_arm64_relocator_rewrite_ADRP(self, insn_ctx); + rewritten = zz_arm64_relocator_rewrite_ADRP(self, insn_ctx, re_insn_ctx); break; case ARM64_INS_B: - rewritten = zz_arm64_relocator_rewrite_B(self, insn_ctx); + rewritten = zz_arm64_relocator_rewrite_B(self, insn_ctx, re_insn_ctx); break; case ARM64_INS_BL: - rewritten = zz_arm64_relocator_rewrite_BL(self, insn_ctx); + rewritten = zz_arm64_relocator_rewrite_BL(self, insn_ctx, re_insn_ctx); break; case ARM64_INS_B_cond: - rewritten = zz_arm64_relocator_rewrite_B_cond(self, insn_ctx); + rewritten = zz_arm64_relocator_rewrite_B_cond(self, insn_ctx, re_insn_ctx); break; default: rewritten = FALSE; @@ -216,5 +299,7 @@ zbool zz_arm64_relocator_write_one(ZzArm64Relocator *self) { } if (!rewritten) zz_arm64_writer_put_bytes(self->output, (zbyte *)&insn_ctx->insn, insn_ctx->size); + re_insn_ctx->relocated_length = + (zaddr)self->output->pc - (zaddr)self->output->base - (zaddr)re_insn_ctx->relocated_offset; return TRUE; } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.h index ae2db64bf..e0d8824e1 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.h @@ -33,14 +33,18 @@ #include "zzdeps/zz.h" typedef struct _ZzArm64Relocator { + zbool try_relocated_again; + zsize try_relocated_length; zpointer input_start; zpointer input_cur; zaddr input_pc; - ZzInstruction *input_insns; - ZzArm64Writer *output; - zuint inpos; zuint outpos; + ZzInstruction *input_insns; + ZzRelocateInstruction *output_insns; + ZzArm64Writer *output; + ZzLiteralInstruction **relocate_literal_insns; + zsize relocate_literal_insns_size; } ZzArm64Relocator; void zz_arm64_relocator_init(ZzArm64Relocator *relocator, zpointer input_code, ZzArm64Writer *writer); @@ -52,9 +56,14 @@ void zz_arm64_relocator_write_all(ZzArm64Relocator *self); void zz_arm64_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes); /* rewrite */ -static zbool zz_arm64_relocator_rewrite_ldr(ZzArm64Relocator *self, const ZzInstruction *insn_ctx); -static zbool zz_arm64_relocator_rewrite_adr(ZzArm64Relocator *self, const ZzInstruction *insn_ctx); -static zbool zz_arm64_relocator_rewrite_b(ZzArm64Relocator *self, const ZzInstruction *insn_ctx); -static zbool zz_arm64_relocator_rewrite_b_cond(ZzArm64Relocator *self, const ZzInstruction *insn_ctx); -static zbool zz_arm64_relocator_rewrite_bl(ZzArm64Relocator *self, const ZzInstruction *insn_ctx); +static zbool zz_arm64_relocator_rewrite_ldr(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx); +static zbool zz_arm64_relocator_rewrite_adr(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx); +static zbool zz_arm64_relocator_rewrite_b(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx); +static zbool zz_arm64_relocator_rewrite_b_cond(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx); +static zbool zz_arm64_relocator_rewrite_bl(ZzArm64Relocator *self, const ZzInstruction *insn_ctx, + ZzRelocateInstruction *re_insn_ctx); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c index 35c4a898d..ab7dcfc74 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c @@ -34,7 +34,7 @@ ZzArm64Writer *zz_arm64_writer_new(zpointer data_ptr) { writer->codedata = data_ptr + t; writer->base = data_ptr + t; - writer->pc = data_ptr + t; + writer->pc = (zaddr)data_ptr + t; writer->size = 0; return writer; } @@ -44,45 +44,67 @@ void zz_arm64_writer_init(ZzArm64Writer *self, zpointer target_addr) { zz_arm64_ void zz_arm64_writer_reset(ZzArm64Writer *self, zpointer data_ptr) { int t = (zaddr)data_ptr % 4; + ZzArm64Writer tmp = {0}; + *self = tmp; + self->codedata = data_ptr + t; self->base = data_ptr + t; - self->pc = data_ptr + t; + self->pc = (zaddr)data_ptr + t; self->size = 0; } +// ======= relocator ======= + +ZzLiteralInstruction *zz_arm64_writer_put_ldr_br_reg_relocate_address(ZzWriter *self, ZzARM64Reg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr) { + + zz_arm64_writer_put_ldr_br_reg_address(self, reg, address); + ZzLiteralInstruction *literal_insn = &(self->literal_insns[self->literal_insn_size - 1]); + *literal_insn_ptr = literal_insn; + return literal_insn; +} + // ======= user custom ======= void zz_arm64_writer_put_ldr_br_reg_address(ZzWriter *self, ZzARM64Reg reg, zaddr address) { + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; zz_arm64_writer_put_ldr_reg_imm(self, reg, (zuint)0x8); zz_arm64_writer_put_br_reg(self, reg); + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_arm64_writer_put_bytes(self, (zpointer)&address, sizeof(zpointer)); } void zz_arm64_writer_put_ldr_blr_b_reg_address(ZzWriter *self, ZzARM64Reg reg, zaddr address) { + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; zz_arm64_writer_put_ldr_reg_imm(self, reg, (zuint)0xc); zz_arm64_writer_put_blr_reg(self, reg); zz_arm64_writer_put_b_imm(self, 0xc); + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_arm64_writer_put_bytes(self, (zpointer)&address, sizeof(zpointer)); } void zz_arm64_writer_put_ldr_b_reg_address(ZzWriter *self, ZzARM64Reg reg, zaddr address) { + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; zz_arm64_writer_put_ldr_reg_imm(self, reg, (zuint)0x8); zz_arm64_writer_put_b_imm(self, 0xc); + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_arm64_writer_put_bytes(self, (zpointer)&address, sizeof(address)); } zsize zz_arm64_writer_near_jump_range_size() { return ((1 << 25) << 2); } void zz_arm64_writer_put_ldr_br_b_reg_address(ZzWriter *self, ZzARM64Reg reg, zaddr address) { + self->literal_insns[self->literal_insn_size].literal_insn_ptr = self->codedata; zz_arm64_writer_put_ldr_reg_imm(self, reg, (zuint)0xc); zz_arm64_writer_put_br_reg(self, reg); zz_arm64_writer_put_b_imm(self, 0xc); + self->literal_insns[self->literal_insn_size++].literal_address_ptr = self->codedata; zz_arm64_writer_put_bytes(self, (zpointer)&address, sizeof(address)); } // ======= default ======= -zpointer zz_arm64_writer_put_ldr_reg_imm(ZzWriter *self, ZzARM64Reg reg, zuint32 offset) { +void zz_arm64_writer_put_ldr_reg_imm(ZzWriter *self, ZzARM64Reg reg, zuint32 offset) { ZzArm64RegInfo ri; zz_arm64_register_describe(reg, &ri); @@ -92,12 +114,11 @@ zpointer zz_arm64_writer_put_ldr_reg_imm(ZzWriter *self, ZzARM64Reg reg, zuint32 Rt_ndx = ri.index; zz_arm64_writer_put_instruction(self, 0x58000000 | imm19 << 5 | Rt_ndx); - return self->pc; + return; } // PAGE: C6-871 -zpointer zz_arm64_writer_put_str_reg_reg_offset(ZzWriter *self, ZzARM64Reg src_reg, ZzARM64Reg dst_reg, - zuint64 offset) { +void zz_arm64_writer_put_str_reg_reg_offset(ZzWriter *self, ZzARM64Reg src_reg, ZzARM64Reg dst_reg, zuint64 offset) { ZzArm64RegInfo rs, rd; zz_arm64_register_describe(src_reg, &rs); @@ -114,11 +135,10 @@ zpointer zz_arm64_writer_put_str_reg_reg_offset(ZzWriter *self, ZzARM64Reg src_r zuint32 imm12 = offset >> size; zz_arm64_writer_put_instruction(self, 0x39000000 | size << 30 | opc << 22 | imm12 << 10 | Rn_ndx << 5 | Rt_ndx); - return self->pc; + return; } -zpointer zz_arm64_writer_put_ldr_reg_reg_offset(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg src_reg, - zuint64 offset) { +void zz_arm64_writer_put_ldr_reg_reg_offset(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg src_reg, zuint64 offset) { ZzArm64RegInfo rs, rd; zz_arm64_register_describe(src_reg, &rs); @@ -135,22 +155,22 @@ zpointer zz_arm64_writer_put_ldr_reg_reg_offset(ZzWriter *self, ZzARM64Reg dst_r zuint32 imm12 = offset >> size; zz_arm64_writer_put_instruction(self, 0x39000000 | size << 30 | opc << 22 | imm12 << 10 | Rn_ndx << 5 | Rt_ndx); - return self->pc; + return; } // C6-562 -zpointer zz_arm64_writer_put_br_reg(ZzWriter *self, ZzARM64Reg reg) { +void zz_arm64_writer_put_br_reg(ZzWriter *self, ZzARM64Reg reg) { ZzArm64RegInfo ri; zz_arm64_register_describe(reg, &ri); zuint32 op = 0, Rn_ndx; Rn_ndx = ri.index; zz_arm64_writer_put_instruction(self, 0xd61f0000 | op << 21 | Rn_ndx << 5); - return self->pc; + return; } // C6-561 -zpointer zz_arm64_writer_put_blr_reg(ZzWriter *self, ZzARM64Reg reg) { +void zz_arm64_writer_put_blr_reg(ZzWriter *self, ZzARM64Reg reg) { ZzArm64RegInfo ri; zz_arm64_register_describe(reg, &ri); @@ -159,29 +179,29 @@ zpointer zz_arm64_writer_put_blr_reg(ZzWriter *self, ZzARM64Reg reg) { Rn_ndx = ri.index; zz_arm64_writer_put_instruction(self, 0xd63f0000 | op << 21 | Rn_ndx << 5); - return self->pc; + return; } // C6-550 -zpointer zz_arm64_writer_put_b_imm(ZzWriter *self, zuint64 offset) { +void zz_arm64_writer_put_b_imm(ZzWriter *self, zuint64 offset) { zuint32 op = 0b0, imm26; imm26 = (offset >> 2) & 0x03ffffff; zz_arm64_writer_put_instruction(self, 0x14000000 | op << 31 | imm26); - return self->pc; + return; } // TODO: standard form, need fix others // PAGE: C6-549 -zpointer zz_arm64_writer_put_b_cond_imm(ZzWriter *self, zuint32 condition, zuint64 imm) { +void zz_arm64_writer_put_b_cond_imm(ZzWriter *self, zuint32 condition, zuint64 imm) { zuint32 imm19, cond; cond = condition; imm19 = (imm >> 2) & 0x7ffff; zz_arm64_writer_put_instruction(self, 0x54000000 | imm19 << 5 | cond); - return self->pc; + return; } // C6-525 -zpointer zz_arm64_writer_put_add_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm) { +void zz_arm64_writer_put_add_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm) { ZzArm64RegInfo rd, rl; zz_arm64_register_describe(dst_reg, &rd); @@ -195,11 +215,11 @@ zpointer zz_arm64_writer_put_add_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, zz_arm64_writer_put_instruction(self, 0x11000000 | sf << 31 | op << 30 | S << 29 | shift << 22 | imm12 << 10 | Rn_ndx << 5 | Rd_ndx); - return self->pc; + return; } // C6-930 -zpointer zz_arm64_writer_put_sub_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm) { +void zz_arm64_writer_put_sub_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm) { ZzArm64RegInfo rd, rl; zz_arm64_register_describe(dst_reg, &rd); @@ -213,21 +233,21 @@ zpointer zz_arm64_writer_put_sub_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, zz_arm64_writer_put_instruction(self, 0x11000000 | sf << 31 | op << 30 | S << 29 | shift << 22 | imm12 << 10 | Rn_ndx << 5 | Rd_ndx); - return self->pc; + return; } -zpointer zz_arm64_writer_put_bytes(ZzWriter *self, zbyte *data, zsize size) { +void zz_arm64_writer_put_bytes(ZzWriter *self, zbyte *data, zsize size) { memcpy(self->codedata, data, size); self->codedata = (zpointer)self->codedata + size; self->pc += size; self->size += size; - return self->pc; + return; } -zpointer zz_arm64_writer_put_instruction(ZzWriter *self, zuint32 insn) { +void zz_arm64_writer_put_instruction(ZzWriter *self, zuint32 insn) { *(zuint32 *)(self->codedata) = insn; self->codedata = (zpointer)self->codedata + sizeof(zuint32); self->pc += 4; self->size += 4; - return self->pc; + return; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.h index 009639f39..2b7370fbd 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.h @@ -50,16 +50,21 @@ void zz_arm64_writer_put_ldr_br_b_reg_address(ZzArm64Writer *self, ZzARM64Reg re // ======= default ======= -zpointer zz_arm64_writer_put_ldr_reg_imm(ZzWriter *self, ZzARM64Reg reg, zuint32 offset); -zpointer zz_arm64_writer_put_str_reg_reg_offset(ZzWriter *self, ZzARM64Reg src_reg, ZzARM64Reg dst_reg, zuint64 offset); -zpointer zz_arm64_writer_put_ldr_reg_reg_offset(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg src_reg, zuint64 offset); -zpointer zz_arm64_writer_put_br_reg(ZzWriter *self, ZzARM64Reg reg); -zpointer zz_arm64_writer_put_blr_reg(ZzWriter *self, ZzARM64Reg reg); -zpointer zz_arm64_writer_put_b_imm(ZzWriter *self, zuint64 offset); -zpointer zz_arm64_writer_put_b_cond_imm(ZzWriter *self, zuint32 condition, zuint64 imm); -zpointer zz_arm64_writer_put_add_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm); -zpointer zz_arm64_writer_put_sub_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm); -zpointer zz_arm64_writer_put_bytes(ZzWriter *self, zbyte *data, zsize size); -zpointer zz_arm64_writer_put_instruction(ZzWriter *self, zuint32 insn); +void zz_arm64_writer_put_ldr_reg_imm(ZzWriter *self, ZzARM64Reg reg, zuint32 offset); +void zz_arm64_writer_put_str_reg_reg_offset(ZzWriter *self, ZzARM64Reg src_reg, ZzARM64Reg dst_reg, zuint64 offset); +void zz_arm64_writer_put_ldr_reg_reg_offset(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg src_reg, zuint64 offset); +void zz_arm64_writer_put_br_reg(ZzWriter *self, ZzARM64Reg reg); +void zz_arm64_writer_put_blr_reg(ZzWriter *self, ZzARM64Reg reg); +void zz_arm64_writer_put_b_imm(ZzWriter *self, zuint64 offset); +void zz_arm64_writer_put_b_cond_imm(ZzWriter *self, zuint32 condition, zuint64 imm); +void zz_arm64_writer_put_add_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm); +void zz_arm64_writer_put_sub_reg_reg_imm(ZzWriter *self, ZzARM64Reg dst_reg, ZzARM64Reg left_reg, zuint64 imm); +void zz_arm64_writer_put_bytes(ZzWriter *self, zbyte *data, zsize size); +void zz_arm64_writer_put_instruction(ZzWriter *self, zuint32 insn); + +// ======= relocator ======= + +ZzLiteralInstruction *zz_arm64_writer_put_ldr_br_reg_relocate_address(ZzWriter *self, ZzARM64Reg reg, zaddr address, + ZzLiteralInstruction **literal_insn_ptr); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c new file mode 100644 index 000000000..9d3b09dde --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c @@ -0,0 +1,550 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "interceptor-arm.h" +#include "zzinfo.h" + +#include + +#define ZZ_THUMB_TINY_REDIRECT_SIZE 4 +#define ZZ_THUMB_FULL_REDIRECT_SIZE 8 +#define ZZ_ARM_TINY_REDIRECT_SIZE 4 +#define ZZ_ARM_FULL_REDIRECT_SIZE 8 + +ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { + ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); + backend->allocator = allocator; + + zz_arm_writer_init(&backend->arm_writer, NULL); + zz_arm_relocator_init(&backend->arm_relocator, NULL, &backend->arm_writer); + zz_thumb_writer_init(&backend->thumb_writer, NULL); + zz_thumb_relocator_init(&backend->thumb_relocator, NULL, &backend->thumb_writer); + + backend->enter_thunk = NULL; + backend->half_thunk = NULL; + backend->leave_thunk = NULL; + + ZzThunkerBuildThunk(backend); + return backend; +} + +ZzCodeSlice *zz_code_patch_thumb_writer(ZzThumbWriter *thumb_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size) { + ZzCodeSlice *code_slice = NULL; + if (range_size > 0) { + code_slice = ZzNewNearCodeSlice(allocator, target_addr, range_size, thumb_writer->size); + } else { + code_slice = ZzNewCodeSlice(allocator, thumb_writer->size + 4); + } + if (!code_slice) + return NULL; + + if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) { + + free(code_slice); + return NULL; + } + return code_slice; +} + +ZzCodeSlice *zz_code_patch_thumb_relocate_writer(ZzThumbRelocator *thumb_relocator, ZzThumbWriter *thumb_writer, + ZzAllocator *allocator, zaddr target_addr, zsize range_size) { + ZzCodeSlice *code_slice = NULL; + if (range_size > 0) { + code_slice = ZzNewNearCodeSlice(allocator, target_addr, range_size, thumb_writer->size); + } else { + code_slice = ZzNewCodeSlice(allocator, thumb_writer->size + 4); + } + if (!code_slice) + return NULL; + + zz_thumb_relocator_relocate_writer(thumb_relocator, (zaddr)code_slice->data); + + if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) { + + free(code_slice); + return NULL; + } + return code_slice; +} + +ZzCodeSlice *zz_code_patch_arm_writer(ZzArmWriter *arm_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size) { + ZzCodeSlice *code_slice = NULL; + if (range_size > 0) { + code_slice = ZzNewNearCodeSlice(allocator, target_addr, range_size, arm_writer->size); + } else { + code_slice = ZzNewCodeSlice(allocator, arm_writer->size + 4); + } + if (!code_slice) + return NULL; + + if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm_writer->base, arm_writer->size)) { + free(code_slice); + return NULL; + } + return code_slice; +} + +ZzCodeSlice *zz_code_patch_arm_relocate_writer(ZzArmRelocator *arm_relocator, ZzArmWriter *arm_writer, + ZzAllocator *allocator, zaddr target_addr, zsize range_size) { + ZzCodeSlice *code_slice = NULL; + if (range_size > 0) { + code_slice = ZzNewNearCodeSlice(allocator, target_addr, range_size, arm_writer->size); + } else { + code_slice = ZzNewCodeSlice(allocator, arm_writer->size + 4); + } + if (!code_slice) + return NULL; + + zz_arm_relocator_relocate_writer(arm_relocator, (zaddr)code_slice->data); + + if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm_writer->base, arm_writer->size)) { + free(code_slice); + return NULL; + } + return code_slice; +} + +ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { + zbool is_thumb = FALSE; + zaddr target_addr = (zaddr)entry->target_ptr; + zuint redirect_limit; + + ZzArmHookFunctionEntryBackend *entry_backend; + entry_backend = (ZzArmHookFunctionEntryBackend *)malloc(sizeof(ZzArmHookFunctionEntryBackend)); + entry->backend = (struct _ZzHookFunctionEntryBackend *)entry_backend; + + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zaddr)entry->target_ptr & ~(zaddr)1; + + if (is_thumb) { + if (entry->try_near_jump) { + entry_backend->redirect_code_size = ZZ_THUMB_TINY_REDIRECT_SIZE; + } else { + zz_thumb_relocator_try_relocate((zpointer)target_addr, ZZ_THUMB_FULL_REDIRECT_SIZE, &redirect_limit); + if (redirect_limit > ZZ_THUMB_TINY_REDIRECT_SIZE && redirect_limit < ZZ_THUMB_FULL_REDIRECT_SIZE) { + entry->try_near_jump = TRUE; + entry_backend->redirect_code_size = ZZ_THUMB_TINY_REDIRECT_SIZE; + } else if (redirect_limit < ZZ_THUMB_TINY_REDIRECT_SIZE) { + return ZZ_FAILED; + } else { + entry_backend->redirect_code_size = ZZ_THUMB_FULL_REDIRECT_SIZE; + if (target_addr % 4) { + entry_backend->redirect_code_size += 2; + } + } + } + self->thumb_relocator.try_relocated_length = entry_backend->redirect_code_size; + } else { + if (entry->try_near_jump) { + entry_backend->redirect_code_size = ZZ_ARM_TINY_REDIRECT_SIZE; + } else { + zz_arm_relocator_try_relocate((zpointer)target_addr, ZZ_ARM_FULL_REDIRECT_SIZE, &redirect_limit); + if (redirect_limit > ZZ_ARM_TINY_REDIRECT_SIZE && redirect_limit < ZZ_ARM_FULL_REDIRECT_SIZE) { + entry->try_near_jump = TRUE; + entry_backend->redirect_code_size = ZZ_ARM_TINY_REDIRECT_SIZE; + } else if (redirect_limit < ZZ_ARM_TINY_REDIRECT_SIZE) { + return ZZ_FAILED; + } else { + entry_backend->redirect_code_size = ZZ_ARM_FULL_REDIRECT_SIZE; + } + } + self->arm_relocator.try_relocated_length = entry_backend->redirect_code_size; + } + + zz_arm_relocator_init(&self->arm_relocator, (zpointer)target_addr, &self->arm_writer); + zz_thumb_relocator_init(&self->thumb_relocator, (zpointer)target_addr, &self->thumb_writer); + return ZZ_SUCCESS; +} + +ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { + zbyte temp_code_slice_data[256] = {0}; + ZzArmWriter *arm_writer = NULL; + ZzArmWriter *thumb_writer = NULL; + ZzCodeSlice *code_slice = NULL; + ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; + ZZSTATUS status = ZZ_SUCCESS; + zbool is_thumb = TRUE; + zaddr target_addr = (zaddr)entry->target_ptr; + + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zaddr)entry->target_ptr & ~(zaddr)1; + + if (is_thumb) { + thumb_writer = &self->thumb_writer; + zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); + + code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, target_addr, + zz_thumb_writer_near_jump_range_size()); + if (code_slice) + entry->on_enter_transfer_trampoline = code_slice->data; + else + return ZZ_FAILED; + } else { + arm_writer = &self->arm_writer; + zz_arm_writer_reset(arm_writer, temp_code_slice_data); + zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); + + code_slice = + zz_code_patch_arm_writer(arm_writer, self->allocator, target_addr, zz_arm_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}; + ZzArmWriter *arm_writer = NULL; + ZzArmWriter *thumb_writer = NULL; + ZzCodeSlice *code_slice = NULL; + ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; + ZZSTATUS status = ZZ_SUCCESS; + zbool is_thumb; + + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + + thumb_writer = &self->thumb_writer; + zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + /* 2 stack space: 1. next_hop 2. entry arg */ + zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); + /* push r7 */ + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + + zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); + + /* pop r7 */ + zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); + + /* jump to enter thunk */ + zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->enter_thunk); + + code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); + if (code_slice) + entry->on_enter_trampoline = code_slice->data + 1; + else + return ZZ_FAILED; + + 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 ((is_thumb && entry_backend->redirect_code_size == ZZ_THUMB_TINY_REDIRECT_SIZE) || + (!is_thumb && entry_backend->redirect_code_size == ZZ_ARM_TINY_REDIRECT_SIZE)) { + ZzBuildEnterTransferTrampoline(self, entry); + } + + free(code_slice); + return status; +} + +ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { + zbyte temp_code_slice_data[256] = {0}; + ZzCodeSlice *code_slice = NULL; + ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; + ZZSTATUS status = ZZ_SUCCESS; + zbool is_thumb = TRUE; + zaddr target_addr = (zaddr)entry->target_ptr; + zpointer target_end_addr = 0; + zpointer restore_target_addr; + + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zaddr)entry->target_ptr & ~(zaddr)1; + + if (is_thumb) { + target_end_addr = (zpointer)((zaddr)entry->target_end_ptr & ~(zaddr)1); + } + + if (is_thumb) { + ZzThumbRelocator *thumb_relocator; + ZzThumbWriter *thumb_writer; + thumb_relocator = &self->thumb_relocator; + thumb_writer = &self->thumb_writer; + + zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + zz_thumb_relocator_reset(thumb_relocator, (zpointer)target_addr, thumb_writer); + zsize tmp_relocator_insn_size = 0; + entry->target_half_ret_addr = 0; + + if (entry->hook_type == HOOK_FUNCTION_TYPE) { + do { + zz_thumb_relocator_read_one(thumb_relocator, NULL); + tmp_relocator_insn_size = thumb_relocator->input_cur - thumb_relocator->input_start; + } while (tmp_relocator_insn_size < entry_backend->redirect_code_size); + zz_thumb_relocator_write_all(thumb_relocator); + } else if (entry->hook_type == HOOK_ADDRESS_TYPE) { + do { + zz_thumb_relocator_read_one(thumb_relocator, NULL); + zz_thumb_relocator_write_one(thumb_relocator); + tmp_relocator_insn_size = thumb_relocator->input_cur - thumb_relocator->input_start; + if (thumb_relocator->input_cur >= target_end_addr && !entry->target_half_ret_addr) { + /* jump to rest target address */ + zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_half_trampoline); + + entry->target_half_ret_addr = (zpointer)(thumb_writer->size + 1); + } + } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || + thumb_relocator->input_cur < target_end_addr); + } + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); + /* jump to rest target address */ + zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)(restore_target_addr + 1)); + + code_slice = zz_code_patch_thumb_relocate_writer(thumb_relocator, thumb_writer, self->allocator, 0, 0); + if (code_slice) + entry->on_invoke_trampoline = code_slice->data + 1; + else + return ZZ_FAILED; + + /* set thumb on_invoke_trampoline */ + } else { + ZzArmRelocator *arm_relocator; + ZzArmWriter *arm_writer; + arm_relocator = &self->arm_relocator; + arm_writer = &self->arm_writer; + + zz_arm_writer_reset(arm_writer, temp_code_slice_data); + zz_arm_relocator_reset(arm_relocator, (zpointer)target_addr, arm_writer); + entry->target_half_ret_addr = 0; + zsize tmp_relocator_insn_size = 0; + + if (entry->hook_type == HOOK_FUNCTION_TYPE) { + do { + zz_arm_relocator_read_one(arm_relocator, NULL); + tmp_relocator_insn_size = arm_relocator->input_cur - arm_relocator->input_start; + } while (tmp_relocator_insn_size < entry_backend->redirect_code_size); + zz_arm_relocator_write_all(arm_relocator); + } else if (entry->hook_type == HOOK_ADDRESS_TYPE) { + do { + zz_arm_relocator_read_one(arm_relocator, NULL); + zz_arm_relocator_write_one(arm_relocator); + tmp_relocator_insn_size = arm_relocator->input_cur - arm_relocator->input_start; + if (arm_relocator->input_cur >= target_end_addr && !entry->target_half_ret_addr) { + /* jump to rest target address */ + zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_half_trampoline); + + entry->target_half_ret_addr = (zpointer)arm_writer->size; + } + } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || + arm_relocator->input_cur < target_end_addr); + } + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); + /* jump to rest target address */ + zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)restore_target_addr); + + code_slice = zz_code_patch_arm_relocate_writer(arm_relocator, arm_writer, self->allocator, 0, 0); + if (code_slice) + entry->on_invoke_trampoline = code_slice->data; + else + return ZZ_FAILED; + /* set arm on_invoke_trampoline */ + } + + if (entry->hook_type == HOOK_ADDRESS_TYPE) { + // update target_half_ret_addr + entry->target_half_ret_addr += (zaddr)code_slice->data; + } + + if (ZzIsEnableDebugMode()) { + char buffer[1024] = {}; + sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildInvokeTrampoline:"); + sprintf(buffer + strlen(buffer), + "LogInfo: on_invoke_trampoline at %p, length: %ld. and will jump to rest code(%p).\n", code_slice->data, + code_slice->size, restore_target_addr); + if (is_thumb) { + sprintf(buffer + strlen(buffer), + "ThumbInstructionFix: origin instruction at %p, end at %p, relocator instruction nums %ld\n", + (&self->thumb_relocator)->input_start, (&self->thumb_relocator)->input_cur, + (&self->thumb_relocator)->inpos); + } else { + sprintf(buffer + strlen(buffer), + "ArmInstructionFix: origin instruction at %p, end at %p, relocator instruction nums %ld\n", + (&self->arm_relocator)->input_start, (&self->arm_relocator)->input_cur, + (&self->arm_relocator)->inpos); + } + + char origin_prologue[256] = {0}; + int t = 0; + zpointer p; + if (is_thumb) { + for (p = (&self->thumb_relocator)->input_start; p < (&self->thumb_relocator)->input_cur; p++, t = t + 5) { + sprintf(origin_prologue + t, "0x%.2x ", *(unsigned char *)p); + } + } else { + for (p = (&self->arm_relocator)->input_start; p < (&self->arm_relocator)->input_cur; p++, t = t + 5) { + sprintf(origin_prologue + t, "0x%.2x ", *(unsigned char *)p); + } + } + sprintf(buffer + strlen(buffer), "origin_prologue: %s\n", origin_prologue); + + ZzInfoLog("%s", buffer); + } + + free(code_slice); + return status; +} + +ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { + zbyte temp_code_slice_data[256] = {0}; + ZzArmWriter *arm_writer = NULL; + ZzArmWriter *thumb_writer = NULL; + ZzCodeSlice *code_slice = NULL; + ZZSTATUS status = ZZ_SUCCESS; + + thumb_writer = &self->thumb_writer; + zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + /* 2 stack space: 1. next_hop 2. entry arg */ + zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); + /* push r7 */ + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + + zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); + + /* pop r7 */ + zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); + + zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->half_thunk); + + code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); + if (code_slice) + entry->on_half_trampoline = code_slice->data + 1; + else + return ZZ_FAILED; + /* set thumb on_half_trampoline */ + + free(code_slice); + return status; +} + +ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { + zbyte temp_code_slice_data[256] = {0}; + ZzCodeSlice *code_slice = NULL; + ZZSTATUS status = ZZ_SUCCESS; + zbool is_thumb = TRUE; + ZzArmWriter *thumb_writer; + + thumb_writer = &self->thumb_writer; + zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + /* 2 stack space: 1. next_hop 2. entry arg */ + zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); + /* push r7 */ + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + + zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); + + /* pop r7 */ + zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); + + zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->leave_thunk); + + code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); + if (code_slice) + entry->on_leave_trampoline = code_slice->data + 1; + else + return ZZ_FAILED; + /* set thumb on_leave_trampoline */ + + if (ZzIsEnableDebugMode()) { + char buffer[1024] = {}; + sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildLeaveTrampoline:"); + sprintf(buffer + strlen(buffer), + "LogInfo: on_leave_trampoline at %p, length: %ld. and will jump to leave_thunk(%p).\n", + code_slice->data, code_slice->size, self->leave_thunk); + ZzInfoLog("%s", buffer); + } + + return ZZ_DONE; +} + +ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { + zbyte temp_code_slice_data[256] = {0}; + ZzCodeSlice *code_slice = NULL; + ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; + ZZSTATUS status = ZZ_SUCCESS; + zbool is_thumb = TRUE; + zaddr target_addr = (zaddr)entry->target_ptr; + + is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); + if (is_thumb) + target_addr = (zaddr)entry->target_ptr & ~(zaddr)1; + + if (is_thumb) { + + ZzThumbWriter *thumb_writer; + thumb_writer = &self->thumb_writer; + zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + thumb_writer->pc = target_addr + 4; + + if (entry_backend->redirect_code_size == ZZ_THUMB_TINY_REDIRECT_SIZE) { + zz_thumb_writer_put_b_imm32(thumb_writer, + (zaddr)entry->on_enter_transfer_trampoline - (zaddr)thumb_writer->pc); + } else { + zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); + } + if (!ZzMemoryPatchCode((zaddr)target_addr, thumb_writer->base, thumb_writer->size)) + return ZZ_FAILED; + } else { + ZzArmWriter *arm_writer; + arm_writer = &self->arm_writer; + zz_arm_writer_reset(arm_writer, temp_code_slice_data); + arm_writer->pc = target_addr + 8; + + if (entry_backend->redirect_code_size == ZZ_ARM_TINY_REDIRECT_SIZE) { + zz_arm_writer_put_b_imm(arm_writer, (zaddr)entry->on_enter_transfer_trampoline - (zaddr)arm_writer->pc); + } else { + zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); + } + if (!ZzMemoryPatchCode((zaddr)target_addr, arm_writer->base, arm_writer->size)) + return ZZ_FAILED; + } + + return ZZ_DONE_HOOK; +} diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.h index 663b7fa40..5563dfb8d 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.h @@ -55,4 +55,9 @@ typedef struct _ZzArmHookFuntionEntryBackend { zuint redirect_code_size; } ZzArmHookFunctionEntryBackend; +ZzCodeSlice *zz_code_patch_thumb_writer(ZzThumbWriter *thumb_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size); +ZzCodeSlice *zz_code_patch_arm_writer(ZzArmWriter *arm_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size); + #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c index 2a0ee694e..970b5124f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c @@ -157,7 +157,6 @@ void function_context_end_invocation(ZzHookFunctionEntry *entry, zpointer next_h ZzFreeCallStack(callstack); } -// A4.1.10 BX void zz_thumb_thunker_build_enter_thunk(ZzWriter *writer) { /* save general registers and sp */ @@ -286,26 +285,15 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + zz_thumb_thunker_build_enter_thunk(thumb_writer); + + code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); + if (code_slice) + self->enter_thunk = code_slice->data + 1; + else + return ZZ_FAILED; + /* set thumb enter_thunk */ - code_slice = NULL; - do { - zz_thumb_thunker_build_enter_thunk(thumb_writer); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, thumb_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); @@ -314,29 +302,16 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { ZzInfoLog("%s", buffer); } - /* set thumb enter_thunk */ - self->enter_thunk = code_slice->data + 1; - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - code_slice = NULL; - do { - zz_thumb_thunker_build_leave_thunk(thumb_writer); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, thumb_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); + zz_thumb_thunker_build_leave_thunk(thumb_writer); + + code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); + if (code_slice) + self->leave_thunk = code_slice->data + 1; + else + return ZZ_FAILED; + /* set thumb leave_thunk */ + if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); @@ -345,31 +320,13 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { ZzInfoLog("%s", buffer); } - /* set thumb leave_thunk */ - self->leave_thunk = code_slice->data + 1; - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - code_slice = NULL; - do { - zz_thumb_thunker_build_half_thunk(thumb_writer); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, thumb_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); - - /* set thumb half_thunk */ - self->half_thunk = code_slice->data + 1; + zz_thumb_thunker_build_half_thunk(thumb_writer); + + code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); + if (code_slice) + self->half_thunk = code_slice->data + 1; + else + return ZZ_FAILED; return status; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c deleted file mode 100644 index feadf7a1c..000000000 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.c +++ /dev/null @@ -1,577 +0,0 @@ -/** - * Copyright 2017 jmpews - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "interceptor-arm.h" -#include "zzinfo.h" - -#include - -#define INSTRUCTION_IS_THUMB(insn_addr) ((insn_addr & 0x1) == 0x1) - -#define ZZ_THUMB_TINY_REDIRECT_SIZE 4 -#define ZZ_THUMB_FULL_REDIRECT_SIZE 8 -#define ZZ_ARM_TINY_REDIRECT_SIZE 4 -#define ZZ_ARM_FULL_REDIRECT_SIZE 8 - -ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { - ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); - backend->allocator = allocator; - - zz_arm_writer_init(&backend->arm_writer, NULL); - zz_arm_relocator_init(&backend->arm_relocator, NULL, &backend->arm_writer); - zz_thumb_writer_init(&backend->thumb_writer, NULL); - zz_thumb_relocator_init(&backend->thumb_relocator, NULL, &backend->thumb_writer); - - backend->enter_thunk = NULL; - backend->half_thunk = NULL; - backend->leave_thunk = NULL; - - ZzThunkerBuildThunk(backend); - return backend; -} - -ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zbool is_thumb = FALSE; - zpointer target_addr = entry->target_ptr; - zuint redirect_limit; - - ZzArmHookFunctionEntryBackend *entry_backend; - entry_backend = (ZzArmHookFunctionEntryBackend *)malloc(sizeof(ZzArmHookFunctionEntryBackend)); - entry->backend = (struct _ZzHookFunctionEntryBackend *)entry_backend; - - is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); - if (is_thumb) - target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - - if (is_thumb) { - if (entry->try_near_jump) { - entry_backend->redirect_code_size = ZZ_THUMB_TINY_REDIRECT_SIZE; - } else { - zz_thumb_relocator_try_relocate(target_addr, ZZ_THUMB_FULL_REDIRECT_SIZE, &redirect_limit); - entry_backend->redirect_code_size = ZZ_THUMB_FULL_REDIRECT_SIZE; - if ((zaddr)target_addr % 4) { - entry_backend->redirect_code_size += 2; - } - } - } else { - if (entry->try_near_jump) { - entry_backend->redirect_code_size = ZZ_ARM_TINY_REDIRECT_SIZE; - } else { - zz_arm_relocator_try_relocate(target_addr, ZZ_ARM_FULL_REDIRECT_SIZE, &redirect_limit); - entry_backend->redirect_code_size = ZZ_ARM_FULL_REDIRECT_SIZE; - } - } - - zz_arm_relocator_init(&self->arm_relocator, target_addr, &self->arm_writer); - zz_thumb_relocator_init(&self->thumb_relocator, target_addr, &self->thumb_writer); - return ZZ_SUCCESS; -} - -ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zbyte temp_code_slice_data[256] = {0}; - ZzArmWriter *arm_writer = NULL; - ZzArmWriter *thumb_writer = NULL; - ZzCodeSlice *code_slice = NULL; - ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - ZZSTATUS status = ZZ_SUCCESS; - zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; - - is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); - if (is_thumb) - target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - - if (is_thumb) { - thumb_writer = &self->thumb_writer; - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - - code_slice = NULL; - do { - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewNearCodeSlice(self->allocator, (zaddr)target_addr, zz_thumb_writer_near_jump_range_size(), - thumb_writer->size); - if (!code_slice) { - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); - entry->on_enter_transfer_trampoline = code_slice->data; - } else { - arm_writer = &self->arm_writer; - zz_arm_writer_reset(arm_writer, temp_code_slice_data); - - code_slice = NULL; - do { - zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); - - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm_writer->base, arm_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewNearCodeSlice(self->allocator, (zaddr)target_addr, zz_arm_writer_near_jump_range_size(), - arm_writer->size); - if (!code_slice) { - return ZZ_FAILED; - } else { - zz_arm_writer_reset(arm_writer, temp_code_slice_data); - arm_writer->pc = code_slice->data + 8; - } - - } while (code_slice); - entry->on_enter_transfer_trampoline = code_slice->data; - } - - 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); - } - return status; -} - -ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zbyte temp_code_slice_data[256] = {0}; - ZzArmWriter *arm_writer = NULL; - ZzArmWriter *thumb_writer = NULL; - ZzCodeSlice *code_slice = NULL; - ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - ZZSTATUS status = ZZ_SUCCESS; - zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; - - thumb_writer = &self->thumb_writer; - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - - is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); - if (is_thumb) - target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - - code_slice = NULL; - do { - /* 2 stack space: 1. next_hop 2. entry arg */ - zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); - /* push r7 */ - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - - zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); - - /* pop r7 */ - zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); - - /* jump to enter thunk */ - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->enter_thunk); - - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - - code_slice = ZzNewCodeSlice(self->allocator, thumb_writer->size + 4); - - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); - - 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); - } - - entry->on_enter_trampoline = code_slice->data + 1; - if ((is_thumb && entry_backend->redirect_code_size == ZZ_THUMB_TINY_REDIRECT_SIZE) || - (!is_thumb && entry_backend->redirect_code_size == ZZ_ARM_TINY_REDIRECT_SIZE)) { - ZzBuildEnterTransferTrampoline(self, entry); - } - - return status; -} - -ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zbyte temp_code_slice_data[256] = {0}; - ZzCodeSlice *code_slice = NULL; - ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - ZZSTATUS status = ZZ_SUCCESS; - zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; - zpointer target_end_addr = 0; - zpointer restore_target_addr; - - is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); - if (is_thumb) - target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - - if (is_thumb) { - target_end_addr = (zpointer)((zaddr)entry->target_end_ptr & ~(zaddr)1); - } - - if (is_thumb) { - ZzThumbRelocator *thumb_relocator; - ZzThumbWriter *thumb_writer; - thumb_relocator = &self->thumb_relocator; - thumb_writer = &self->thumb_writer; - - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - - code_slice = NULL; - do { - zz_thumb_relocator_reset(thumb_relocator, target_addr, thumb_writer); - zsize tmp_relocator_insn_size = 0; - entry->target_half_ret_addr = 0; - - if (entry->hook_type == HOOK_FUNCTION_TYPE) { - do { - zz_thumb_relocator_read_one(thumb_relocator, NULL); - tmp_relocator_insn_size = thumb_relocator->input_cur - thumb_relocator->input_start; - } while (tmp_relocator_insn_size < entry_backend->redirect_code_size); - zz_thumb_relocator_write_all(thumb_relocator); - } else if (entry->hook_type == HOOK_ADDRESS_TYPE) { - do { - zz_thumb_relocator_read_one(thumb_relocator, NULL); - zz_thumb_relocator_write_one(thumb_relocator); - tmp_relocator_insn_size = thumb_relocator->input_cur - thumb_relocator->input_start; - if (thumb_relocator->input_cur >= target_end_addr && !entry->target_half_ret_addr) { - /* jump to rest target address */ - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, - (zaddr)entry->on_half_trampoline); - - entry->target_half_ret_addr = (zpointer)(thumb_writer->size + 1); - } - } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || - thumb_relocator->input_cur < target_end_addr); - } - - restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); - - /* jump to rest target address */ - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)(restore_target_addr + 1)); - - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, thumb_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); - - /* set thumb on_invoke_trampoline */ - entry->on_invoke_trampoline = code_slice->data + 1; - } else { - ZzArmRelocator *arm_relocator; - ZzArmWriter *arm_writer; - arm_relocator = &self->arm_relocator; - arm_writer = &self->arm_writer; - - zz_arm_writer_reset(arm_writer, temp_code_slice_data); - code_slice = NULL; - - do { - zz_arm_relocator_reset(arm_relocator, target_addr, arm_writer); - entry->target_half_ret_addr = 0; - zsize tmp_relocator_insn_size = 0; - - if (entry->hook_type == HOOK_FUNCTION_TYPE) { - do { - zz_arm_relocator_read_one(arm_relocator, NULL); - tmp_relocator_insn_size = arm_relocator->input_cur - arm_relocator->input_start; - } while (tmp_relocator_insn_size < entry_backend->redirect_code_size); - zz_arm_relocator_write_all(arm_relocator); - } else if (entry->hook_type == HOOK_ADDRESS_TYPE) { - do { - zz_arm_relocator_read_one(arm_relocator, NULL); - zz_arm_relocator_write_one(arm_relocator); - tmp_relocator_insn_size = arm_relocator->input_cur - arm_relocator->input_start; - if (arm_relocator->input_cur >= target_end_addr && !entry->target_half_ret_addr) { - /* jump to rest target address */ - zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_half_trampoline); - - entry->target_half_ret_addr = (zpointer)arm_writer->size; - } - } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || - arm_relocator->input_cur < target_end_addr); - } - - restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); - - /* jump to rest target address */ - zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)restore_target_addr); - - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm_writer->base, arm_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, arm_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm_writer_reset(arm_writer, temp_code_slice_data); - arm_writer->pc = code_slice->data + 8; - } - - } while (code_slice); - - /* set arm on_invoke_trampoline */ - entry->on_invoke_trampoline = code_slice->data; - } - - if (entry->hook_type == HOOK_ADDRESS_TYPE) { - // update target_half_ret_addr - entry->target_half_ret_addr += (zaddr)code_slice->data; - } - - if (ZzIsEnableDebugMode()) { - char buffer[1024] = {}; - sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildInvokeTrampoline:"); - sprintf(buffer + strlen(buffer), - "LogInfo: on_invoke_trampoline at %p, length: %ld. and will jump to rest code(%p).\n", code_slice->data, - code_slice->size, restore_target_addr); - if (is_thumb) { - sprintf(buffer + strlen(buffer), - "ThumbInstructionFix: origin instruction at %p, end at %p, relocator instruction nums %ld\n", - (&self->thumb_relocator)->input_start, (&self->thumb_relocator)->input_cur, - (&self->thumb_relocator)->inpos); - } else { - sprintf(buffer + strlen(buffer), - "ArmInstructionFix: origin instruction at %p, end at %p, relocator instruction nums %ld\n", - (&self->arm_relocator)->input_start, (&self->arm_relocator)->input_cur, - (&self->arm_relocator)->inpos); - } - - char origin_prologue[256] = {0}; - int t = 0; - if (is_thumb) { - for (zpointer p = (&self->thumb_relocator)->input_start; p < (&self->thumb_relocator)->input_cur; - p++, t = t + 5) { - sprintf(origin_prologue + t, "0x%.2x ", *(unsigned char *)p); - } - } else { - for (zpointer p = (&self->arm_relocator)->input_start; p < (&self->arm_relocator)->input_cur; - p++, t = t + 5) { - sprintf(origin_prologue + t, "0x%.2x ", *(unsigned char *)p); - } - } - sprintf(buffer + strlen(buffer), "origin_prologue: %s\n", origin_prologue); - - ZzInfoLog("%s", buffer); - } - - return status; -} - -ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zbyte temp_code_slice_data[256] = {0}; - ZzArmWriter *arm_writer = NULL; - ZzArmWriter *thumb_writer = NULL; - ZzCodeSlice *code_slice = NULL; - ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - ZZSTATUS status = ZZ_SUCCESS; - zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; - - thumb_writer = &self->thumb_writer; - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - - is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); - if (is_thumb) - target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - - code_slice = NULL; - do { - /* 2 stack space: 1. next_hop 2. entry arg */ - zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); - /* push r7 */ - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - - zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); - - /* pop r7 */ - zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); - - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->half_thunk); - - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, thumb_writer->size + 4); - - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); - - /* set thumb on_half_trampoline */ - entry->on_half_trampoline = code_slice->data + 1; - - return status; -} - -ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zbyte temp_code_slice_data[256] = {0}; - ZzCodeSlice *code_slice = NULL; - ZZSTATUS status = ZZ_SUCCESS; - zbool is_thumb = TRUE; - ZzArmWriter *thumb_writer; - - ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - - zpointer target_addr = entry->target_ptr; - thumb_writer = &self->thumb_writer; - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - - is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); - if (is_thumb) - target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - - code_slice = NULL; - do { - /* 2 stack space: 1. next_hop 2. entry arg */ - zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); - /* push r7 */ - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - - zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); - - /* pop r7 */ - zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); - - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->leave_thunk); - - if (code_slice) { - - if (!ZzMemoryPatchCode((zaddr)code_slice->data, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, thumb_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = code_slice->data + 4; - } - } while (code_slice); - - if (ZzIsEnableDebugMode()) { - char buffer[1024] = {}; - sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildLeaveTrampoline:"); - sprintf(buffer + strlen(buffer), - "LogInfo: on_leave_trampoline at %p, length: %ld. and will jump to leave_thunk(%p).\n", - code_slice->data, code_slice->size, self->leave_thunk); - ZzInfoLog("%s", buffer); - } - - /* set thumb on_leave_trampoline */ - entry->on_leave_trampoline = code_slice->data + 1; - - return ZZ_DONE; -} - -ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zbyte temp_code_slice_data[256] = {0}; - ZzCodeSlice *code_slice = NULL; - ZzArmHookFunctionEntryBackend *entry_backend = (ZzArmHookFunctionEntryBackend *)entry->backend; - ZZSTATUS status = ZZ_SUCCESS; - zbool is_thumb = TRUE; - zpointer target_addr = entry->target_ptr; - - is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); - if (is_thumb) - target_addr = (zpointer)((zaddr)entry->target_ptr & ~(zaddr)1); - - if (is_thumb) { - - ZzThumbWriter *thumb_writer; - thumb_writer = &self->thumb_writer; - zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - thumb_writer->pc = target_addr + 4; - - if (entry_backend->redirect_code_size == ZZ_THUMB_TINY_REDIRECT_SIZE) { - zz_thumb_writer_put_b_imm32(thumb_writer, - (zaddr)entry->on_enter_transfer_trampoline - (zaddr)thumb_writer->pc); - } else { - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); - } - if (!ZzMemoryPatchCode((zaddr)target_addr, thumb_writer->base, thumb_writer->size)) - return ZZ_FAILED; - } else { - ZzArmWriter *arm_writer; - arm_writer = &self->arm_writer; - zz_arm_writer_reset(arm_writer, temp_code_slice_data); - arm_writer->pc = target_addr + 8; - - if (entry_backend->redirect_code_size == ZZ_ARM_TINY_REDIRECT_SIZE) { - zz_arm_writer_put_b_imm(arm_writer, (zaddr)entry->on_enter_transfer_trampoline - (zaddr)arm_writer->pc); - } else { - zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); - } - if (!ZzMemoryPatchCode((zaddr)target_addr, arm_writer->base, arm_writer->size)) - return ZZ_FAILED; - } - - return ZZ_DONE_HOOK; -} diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.h deleted file mode 100644 index 6548be5b4..000000000 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/trampoline-arm.h +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright 2017 jmpews - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/trampoline-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c similarity index 52% rename from VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/trampoline-arm64.c rename to VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c index f69b277b5..027745f1f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/trampoline-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c @@ -41,8 +41,44 @@ ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { return backend; } +ZzCodeSlice *zz_code_patch_arm64_writer(ZzArm64Writer *arm64_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size) { + ZzCodeSlice *code_slice = NULL; + if (range_size > 0) { + code_slice = ZzNewNearCodeSlice(allocator, target_addr, range_size, arm64_writer->size); + } else { + code_slice = ZzNewCodeSlice(allocator, arm64_writer->size + 4); + } + if (!code_slice) + return NULL; + + if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) { + free(code_slice); + return NULL; + } + return code_slice; +} + +ZzCodeSlice *zz_code_patch_arm64_relocate_writer(ZzArm64Relocator *relocator, ZzArm64Writer *arm64_writer, + ZzAllocator *allocator, zaddr target_addr, zsize range_size) { + ZzCodeSlice *code_slice = NULL; + if (range_size > 0) { + code_slice = ZzNewNearCodeSlice(allocator, target_addr, range_size, arm64_writer->size); + } else { + code_slice = ZzNewCodeSlice(allocator, arm64_writer->size + 4); + } + if (!code_slice) + return NULL; + + if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) { + free(code_slice); + return NULL; + } + return code_slice; +} + ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { - zpointer target_addr = entry->target_ptr; + zaddr target_addr = (zaddr)entry->target_ptr; zuint redirect_limit; ZzArm64HookFunctionEntryBackend *entry_backend; @@ -52,94 +88,41 @@ ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *en if (entry->try_near_jump) { entry_backend->redirect_code_size = ZZ_ARM64_TINY_REDIRECT_SIZE; } else { - zz_arm64_relocator_try_relocate(target_addr, ZZ_ARM64_FULL_REDIRECT_SIZE, &redirect_limit); - entry_backend->redirect_code_size = ZZ_ARM64_FULL_REDIRECT_SIZE; + zz_arm64_relocator_try_relocate((zpointer)target_addr, ZZ_ARM64_FULL_REDIRECT_SIZE, &redirect_limit); + if (redirect_limit > ZZ_ARM64_TINY_REDIRECT_SIZE && redirect_limit < ZZ_ARM64_FULL_REDIRECT_SIZE) { + entry->try_near_jump = TRUE; + entry_backend->redirect_code_size = ZZ_ARM64_TINY_REDIRECT_SIZE; + } else if (redirect_limit < ZZ_ARM64_TINY_REDIRECT_SIZE) { + return ZZ_FAILED; + } else { + entry_backend->redirect_code_size = ZZ_ARM64_FULL_REDIRECT_SIZE; + } } - zz_arm64_relocator_init(&self->arm64_relocator, target_addr, &self->arm64_writer); + self->arm64_relocator.try_relocated_length = entry_backend->redirect_code_size; + zz_arm64_relocator_init(&self->arm64_relocator, (zpointer)target_addr, &self->arm64_writer); return ZZ_SUCCESS; } -// __attribute__((__naked__)) void on_enter_trampoline_template() { -// __asm__ volatile( -// /* store entry address and reserve space for next hop */ -// "sub sp, sp, 0x10\n" -// "ldr x17, #0x8\n" -// "b #0xc\n" -// /* entry address */ -// ".long 0x0\n" -// ".long 0x0\n" -// "str x17, [sp]\n" -// "ldr x17, #0x8\n" -// "br x17\n" -// /* enter_thunk address */ -// ".long 0x0\n" -// ".long 0x0"); -// } - -// __attribute__((__naked__)) void on_inovke_trampoline_template() { -// __asm__ volatile( -// /* fixed instruction */ -// "nop\n" -// "nop\n" -// "nop\n" -// "nop\n" -// "nop\n" -// "nop\n" -// "nop\n" -// "nop\n" -// "ldr x17, #8\n" -// "br x17\n" -// /* rest of orgin function address */ -// ".long 0x0\n" -// ".long 0x0"); -// } - -// __attribute__((__naked__)) void on_leave_trampoline_template() { -// __asm__ volatile( -// /* store entry address and reserve space for next hop */ -// "sub sp, sp, 0x10\n" -// "ldr x17, #0x8\n" -// "b #0xc\n" -// /* entry address */ -// ".long 0x0\n" -// ".long 0x0\n" -// "str x17, [sp]\n" -// "ldr x17, #0x8\n" -// "br x17\n" -// /* leave_thunk address */ -// ".long 0x0\n" -// ".long 0x0"); -// } 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; - zpointer target_addr = entry->target_ptr; + zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - code_slice = NULL; - do { - zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry->on_enter_trampoline); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewNearCodeSlice(self->allocator, (zaddr)entry->target_ptr, - zz_arm64_writer_near_jump_range_size(), arm64_writer->size + 4); - if (!code_slice) { - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); - entry->on_enter_transfer_trampoline = 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] = {}; @@ -157,41 +140,25 @@ ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; - zpointer target_addr = entry->target_ptr; + zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - code_slice = NULL; - do { - /* 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); + /* 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); - /* jump to enter thunk */ - zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->enter_thunk); + 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); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } + /* jump to enter thunk */ + zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->enter_thunk); - if (!code_slice) - code_slice = ZzNewCodeSlice(self->allocator, arm64_writer->size + 4); - - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); + 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; if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildEnterTrampoline:"); @@ -201,8 +168,6 @@ ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzInfoLog("%s", buffer); } - entry->on_enter_trampoline = code_slice->data; - if (entry_backend->redirect_code_size == ZZ_ARM64_TINY_REDIRECT_SIZE) { ZzBuildEnterTransferTrampoline(self, entry); } @@ -215,7 +180,7 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; - zpointer target_addr = entry->target_ptr; + zaddr target_addr = (zaddr)entry->target_ptr; zpointer restore_target_addr; ZzArm64Relocator *arm64_relocator; @@ -225,55 +190,42 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - code_slice = NULL; - do { - zz_arm64_relocator_reset(arm64_relocator, target_addr, arm64_writer); - zsize tmp_relocator_insn_size = 0; - entry->target_half_ret_addr = 0; - - if (entry->hook_type == HOOK_FUNCTION_TYPE) { - do { - zz_arm64_relocator_read_one(arm64_relocator, NULL); - tmp_relocator_insn_size = arm64_relocator->input_cur - arm64_relocator->input_start; - } while (tmp_relocator_insn_size < entry_backend->redirect_code_size); - zz_arm64_relocator_write_all(arm64_relocator); - } else if (entry->hook_type == HOOK_ADDRESS_TYPE) { - do { - zz_arm64_relocator_read_one(arm64_relocator, NULL); - zz_arm64_relocator_write_one(arm64_relocator); - tmp_relocator_insn_size = arm64_relocator->input_cur - arm64_relocator->input_start; - if (arm64_relocator->input_cur >= entry->target_end_ptr && !entry->target_half_ret_addr) { - /* jump to rest target address */ - zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, - (zaddr)entry->on_half_trampoline); - - entry->target_half_ret_addr = (zpointer)arm64_writer->size; - } - } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || - arm64_relocator->input_cur < entry->target_end_ptr); - } + zz_arm64_relocator_reset(arm64_relocator, (zpointer)target_addr, arm64_writer); + zsize tmp_relocator_insn_size = 0; + entry->target_half_ret_addr = 0; + + if (entry->hook_type == HOOK_FUNCTION_TYPE) { + do { + zz_arm64_relocator_read_one(arm64_relocator, NULL); + tmp_relocator_insn_size = arm64_relocator->input_cur - arm64_relocator->input_start; + } while (tmp_relocator_insn_size < entry_backend->redirect_code_size); + zz_arm64_relocator_write_all(arm64_relocator); + } else if (entry->hook_type == HOOK_ADDRESS_TYPE) { + do { + zz_arm64_relocator_read_one(arm64_relocator, NULL); + zz_arm64_relocator_write_one(arm64_relocator); + tmp_relocator_insn_size = arm64_relocator->input_cur - arm64_relocator->input_start; + if (arm64_relocator->input_cur >= entry->target_end_ptr && !entry->target_half_ret_addr) { + /* jump to rest target address */ + zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, + (zaddr)entry->on_half_trampoline); + + entry->target_half_ret_addr = (zpointer)arm64_writer->size; + } + } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || + arm64_relocator->input_cur < entry->target_end_ptr); + } - restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); - /* jump to rest target address */ - zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)restore_target_addr); + /* jump to rest target address */ + zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)restore_target_addr); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, arm64_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); + code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); + if (code_slice) + entry->on_invoke_trampoline = code_slice->data; + else + return ZZ_FAILED; if (ZzIsEnableDebugMode()) { char buffer[1024] = {0}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildInvokeTrampoline:"); @@ -287,8 +239,8 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry char origin_prologue[256] = {0}; int t = 0; - for (zpointer p = (&self->arm64_relocator)->input_start; p < (&self->arm64_relocator)->input_cur; - p++, t = t + 5) { + zpointer p; + for (p = (&self->arm64_relocator)->input_start; p < (&self->arm64_relocator)->input_cur; p++, t = t + 5) { sprintf(origin_prologue + t, "0x%.2x ", *(unsigned char *)p); } sprintf(buffer + strlen(buffer), "origin_prologue: %s\n", origin_prologue); @@ -300,7 +252,6 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry // update target_half_ret_addr entry->target_half_ret_addr += (zaddr)code_slice->data; } - entry->on_invoke_trampoline = code_slice->data; return status; } @@ -310,42 +261,24 @@ ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry * ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; - zpointer target_addr = entry->target_ptr; + zaddr target_addr = (zaddr)entry->target_ptr; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - code_slice = NULL; - do { - /* 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); + /* 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_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->half_thunk); + 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); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } + zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->half_thunk); - if (!code_slice) - code_slice = ZzNewCodeSlice(self->allocator, arm64_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); - - /* set arm64 on_half_trampoline */ - entry->on_half_trampoline = code_slice->data; + 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; } @@ -354,37 +287,26 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry zbyte temp_code_slice_data[256] = {0}; ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; - zpointer target_addr = entry->target_ptr; + zaddr target_addr = (zaddr)entry->target_ptr; ZzArm64Writer *arm64_writer; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - do { - /* 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); + /* 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); + 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 leave thunk */ - zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->leave_thunk); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, arm64_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); + /* jump to leave thunk */ + zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->leave_thunk); + + code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); + if (code_slice) + entry->on_leave_trampoline = code_slice->data; + else + return ZZ_FAILED; if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; @@ -395,9 +317,6 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzInfoLog("%s", buffer); } - /* set arm64 on_leave_trampoline */ - entry->on_leave_trampoline = code_slice->data; - return ZZ_DONE; } @@ -406,7 +325,7 @@ ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *e ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; ZZSTATUS status = ZZ_SUCCESS; - zpointer target_addr = entry->target_ptr; + zaddr target_addr = (zaddr)entry->target_ptr; ZzArm64Writer *arm64_writer; arm64_writer = &self->arm64_writer; @@ -458,8 +377,8 @@ ZZSTATUS ZzActivateSolidifyTrampoline(ZzHookFunctionEntry *entry, zaddr target_f ZzHookFunctionEntryNoJB *nojb_entry = (ZzHookFunctionEntryNoJB *)(data_seg_cmd->vmaddr + sizeof(ZzHookFunctionEntryNoJB) + aslr_slide); - - for (unsigned long i = 0; i < nojb_backend->num_of_entry; i++) { + unsigned long i; + for (i = 0; i < nojb_backend->num_of_entry; i++) { nojb_entry = &nojb_entry[i]; if ((zaddr)nojb_entry->target_fileoff == target_fileoff) { nojb_entry->entry_address = entry; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.h index 77eef0514..8001aca0b 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.h @@ -57,4 +57,7 @@ void leave_thunk_template(); void on_enter_trampoline_template(); void on_invoke_trampoline_template(); void on_leave_trampoline_template(); + +ZzCodeSlice *zz_code_patch_arm64_writer(ZzArm64Writer *arm64_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c index b97921b01..4286563a9 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c @@ -497,29 +497,14 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - code_slice = NULL; - do { - zz_arm64_thunker_build_enter_thunk(arm64_writer); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, arm64_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); - - /* set arm64 enter_thunk */ - // self->enter_thunk = code_slice->data; - self->enter_thunk = (void *)enter_thunk_template; + zz_arm64_thunker_build_enter_thunk(arm64_writer); + + code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); + if (code_slice) + self->enter_thunk = (void *)enter_thunk_template; + else + return ZZ_FAILED; + if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); @@ -529,25 +514,13 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { } zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - code_slice = NULL; - do { - zz_arm64_thunker_build_leave_thunk(arm64_writer); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, arm64_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); + zz_arm64_thunker_build_leave_thunk(arm64_writer); + + 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; if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); @@ -555,33 +528,14 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { code_slice->size); ZzInfoLog("%s", buffer); } - - /* set arm64 leave_thunk */ - self->leave_thunk = code_slice->data; - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - code_slice = NULL; - do { - zz_arm64_thunker_build_half_thunk(arm64_writer); - if (code_slice) { - if (!ZzMemoryPatchCode((zaddr)code_slice->data, arm64_writer->base, arm64_writer->size)) - return ZZ_FAILED; - break; - } - code_slice = ZzNewCodeSlice(self->allocator, arm64_writer->size + 4); - if (!code_slice) { -#if defined(DEBUG_MODE) - debug_break(); -#endif - return ZZ_FAILED; - } else { - zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - arm64_writer->pc = code_slice->data; - } - } while (code_slice); - - /* set arm64 half_thunk */ - self->half_thunk = code_slice->data; + zz_arm64_thunker_build_half_thunk(arm64_writer); + + 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; return status; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/stack.c b/VirtualApp/lib/src/main/jni/HookZz/src/stack.c index 8637f4f27..97ec0e18a 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/stack.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/stack.c @@ -74,8 +74,8 @@ zbool ZzPushCallStack(ZzThreadStack *stack, ZzCallStack *callstack) { return FALSE; if (stack->size >= stack->capacity) { - ZzCallStack **callstacks = (ZzCallStack **)realloc( - stack->callstacks, sizeof(ZzCallStack *) * (stack->capacity) * 2); + ZzCallStack **callstacks = + (ZzCallStack **)realloc(stack->callstacks, sizeof(ZzCallStack *) * (stack->capacity) * 2); if (!callstacks) return FALSE; stack->callstacks = callstacks; @@ -93,7 +93,8 @@ zpointer ZzGetCallStackData(CallStack *callstack_ptr, char *key) { ZzCallStack *callstack = (ZzCallStack *)callstack_ptr; if (!callstack) return NULL; - for (int i = 0; i < callstack->size; ++i) { + int i; + for (i = 0; i < callstack->size; ++i) { if (!strcmp(callstack->items[i].key, key)) { return callstack->items[i].value; } @@ -105,8 +106,8 @@ ZzCallStackItem *ZzNewCallStackData(ZzCallStack *callstack) { if (!callstack) return NULL; if (callstack->size >= callstack->capacity) { - ZzCallStackItem *callstackitems = (ZzCallStackItem *)realloc( - callstack->items, sizeof(ZzCallStackItem) * callstack->capacity * 2); + ZzCallStackItem *callstackitems = + (ZzCallStackItem *)realloc(callstack->items, sizeof(ZzCallStackItem) * callstack->capacity * 2); if (!callstackitems) return NULL; callstack->items = callstackitems; @@ -115,8 +116,7 @@ ZzCallStackItem *ZzNewCallStackData(ZzCallStack *callstack) { return &(callstack->items[callstack->size++]); } -zbool ZzSetCallStackData(CallStack *callstack_ptr, char *key, zpointer value_ptr, - zsize value_size) { +zbool ZzSetCallStackData(CallStack *callstack_ptr, char *key, zpointer value_ptr, zsize value_size) { ZzCallStack *callstack = (ZzCallStack *)callstack_ptr; if (!callstack) return FALSE; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/writer.h b/VirtualApp/lib/src/main/jni/HookZz/src/writer.h index 62cd18ae1..a1036f62c 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/writer.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/writer.h @@ -19,11 +19,22 @@ #include "hookzz.h" +#define MAX_LITERAL_INSN_SIZE 128 + +typedef struct _ZzLiteralInstruction { + zpointer literal_insn_ptr; + zaddr *literal_address_ptr; +} ZzLiteralInstruction; + typedef struct _ZzWriter { - zpointer *codedata; + zpointer codedata; zpointer base; - zpointer pc; - zuint size; + zaddr pc; + zsize size; + + ZzLiteralInstruction literal_insns[MAX_LITERAL_INSN_SIZE]; + zsize literal_insn_size; + } ZzWriter; #endif diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/zzdefs.h b/VirtualApp/lib/src/main/jni/HookZz/src/zzdefs.h index 7135936fe..9630b0f89 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/zzdefs.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/zzdefs.h @@ -38,4 +38,6 @@ #define ZZ_INT26_MASK 0x03ffffff #define ZZ_INT28_MASK 0x0fffffff -#define THUMB_FUNCTION_ADDRESS(target_addr) (void *)((unsigned long)target_addr & ~(unsigned long)1) \ No newline at end of file +#define THUMB_FUNCTION_ADDRESS(target_addr) (void *)((unsigned long)target_addr & ~(unsigned long)1) +#define INSTRUCTION_IS_THUMB(insn_addr) ((insn_addr & 0x1) == 0x1) +#define ALIGN_4(target_addr) ((unsigned long)target_addr & ~(unsigned long)3) \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/macho-utils-darwin.c b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/macho-utils-darwin.c index e1c25d7aa..1ab97a980 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/macho-utils-darwin.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/macho-utils-darwin.c @@ -55,8 +55,7 @@ zpointer zz_macho_get_dyld_load_address_via_task(task_t task) { KR_ERROR(kr); return 0; } - struct dyld_all_image_infos *allImageInfos = - (struct dyld_all_image_infos *)infoData.all_image_info_addr; + struct dyld_all_image_infos *allImageInfos = (struct dyld_all_image_infos *)infoData.all_image_info_addr; allImageInfos = (struct dyld_all_image_infos *)malloc(sizeof(struct dyld_all_image_infos)); if (zz_vm_read_data_via_task(task, infoData.all_image_info_addr, allImageInfos, sizeof(struct dyld_all_image_infos))) { @@ -76,14 +75,14 @@ task_t zz_darwin_get_task_via_pid(int pid) { return t; } -struct segment_command_64 *zz_macho_get_segment_64_via_name(struct mach_header_64 *header, - char *segment_name) { +struct segment_command_64 *zz_macho_get_segment_64_via_name(struct mach_header_64 *header, char *segment_name) { struct load_command *load_cmd; struct segment_command_64 *seg_cmd_64; struct section_64 *sect_64; load_cmd = (zpointer)header + sizeof(struct mach_header_64); - for (zsize i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { + zsize i; + for (i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { if (load_cmd->cmd == LC_SEGMENT_64) { seg_cmd_64 = (struct segment_command_64 *)load_cmd; if (!strcmp(seg_cmd_64->segname, segment_name)) { @@ -94,20 +93,19 @@ struct segment_command_64 *zz_macho_get_segment_64_via_name(struct mach_header_6 return NULL; } -struct section_64 *zz_macho_get_section_64_via_name(struct mach_header_64 *header, - char *sect_name) { +struct section_64 *zz_macho_get_section_64_via_name(struct mach_header_64 *header, char *sect_name) { struct load_command *load_cmd; struct segment_command_64 *seg_cmd_64; struct section_64 *sect_64; load_cmd = (zpointer)header + sizeof(struct mach_header_64); - for (zsize i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { + zsize i; + zsize j; + for (i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { if (load_cmd->cmd == LC_SEGMENT_64) { seg_cmd_64 = (struct segment_command_64 *)load_cmd; - sect_64 = - (struct section_64 *)((zpointer)seg_cmd_64 + sizeof(struct segment_command_64)); - for (zsize j = 0; j < seg_cmd_64->nsects; - j++, sect_64 = (zpointer)sect_64 + sizeof(struct section_64)) { + sect_64 = (struct section_64 *)((zpointer)seg_cmd_64 + sizeof(struct segment_command_64)); + for (j = 0; j < seg_cmd_64->nsects; j++, sect_64 = (zpointer)sect_64 + sizeof(struct section_64)) { if (!strcmp(sect_64->sectname, sect_name)) { return sect_64; } @@ -121,9 +119,10 @@ struct load_command *zz_macho_get_load_command_via_cmd(struct mach_header_64 *he struct load_command *load_cmd; struct segment_command_64 *seg_cmd_64; struct section_64 *sect_64; + zsize i; load_cmd = (zpointer)header + sizeof(struct mach_header_64); - for (zsize i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { + for (i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { if (load_cmd->cmd == cmd) { return load_cmd; } @@ -139,13 +138,13 @@ zpointer zz_macho_get_symbol_via_name(struct mach_header_64 *header, const char zz_macho_get_segment_64_via_name((struct mach_header_64 *)header, (char *)"__LINKEDIT"); zsize slide = (zaddr)header - (zaddr)seg_cmd_64->vmaddr; zsize linkEditBase = seg_cmd_64_linkedit->vmaddr - seg_cmd_64_linkedit->fileoff + slide; - struct symtab_command *symtab = - (struct symtab_command *)zz_macho_get_load_command_via_cmd(header, LC_SYMTAB); + struct symtab_command *symtab = (struct symtab_command *)zz_macho_get_load_command_via_cmd(header, LC_SYMTAB); char *sym_str_table = (char *)linkEditBase + symtab->stroff; struct nlist_64 *sym_table = (struct nlist_64 *)(linkEditBase + symtab->symoff); - for (int i = 0; i < symtab->nsyms; i++) { + int i; + for (i = 0; i < symtab->nsyms; i++) { if (sym_table[i].n_value && !strcmp(name, &sym_str_table[sym_table[i].n_un.n_strx])) { return (void *)(uint64_t)(sym_table[i].n_value + slide); } @@ -158,9 +157,10 @@ zpointer zz_macho_get_section_64_address_via_name(struct mach_header_64 *header, struct segment_command_64 *seg_cmd_64; struct section_64 *sect_64; zsize slide, linkEditBase; + zsize i, j; load_cmd = (zpointer)header + sizeof(struct mach_header_64); - for (zsize i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { + for (i = 0; i < header->ncmds; i++, load_cmd = (zpointer)load_cmd + load_cmd->cmdsize) { if (load_cmd->cmd == LC_SEGMENT_64) { seg_cmd_64 = (struct segment_command_64 *)load_cmd; if ((seg_cmd_64->fileoff == 0) && (seg_cmd_64->filesize != 0)) { @@ -169,10 +169,8 @@ zpointer zz_macho_get_section_64_address_via_name(struct mach_header_64 *header, if (strcmp(seg_cmd_64->segname, "__LINKEDIT") == 0) { linkEditBase = seg_cmd_64->vmaddr - seg_cmd_64->fileoff + slide; } - sect_64 = - (struct section_64 *)((zpointer)seg_cmd_64 + sizeof(struct segment_command_64)); - for (zsize j = 0; j < seg_cmd_64->nsects; - j++, sect_64 = (zpointer)sect_64 + sizeof(struct section_64)) { + sect_64 = (struct section_64 *)((zpointer)seg_cmd_64 + sizeof(struct segment_command_64)); + for (j = 0; j < seg_cmd_64->nsects; j++, sect_64 = (zpointer)sect_64 + sizeof(struct section_64)) { if (!strcmp(sect_64->sectname, sect_name)) { return (zpointer)(sect_64->addr + slide); } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/memory-utils-darwin.c b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/memory-utils-darwin.c index 75806fa4d..4ac4cbbba 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/memory-utils-darwin.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/darwin/memory-utils-darwin.c @@ -332,8 +332,8 @@ zpointer zz_vm_search_code_cave(zaddr address, zsize range_size, zsize size) { MemoryLayout *mlayout = zz_vm_get_memory_layout_via_task(mach_task_self()); - for (int i = 0; i < mlayout->size; i++) { - + int i; + for (i = 0; i < mlayout->size; i++) { if (mlayout->mem[i].flags == (1 << 0 | 1 << 2)) { search_start = (zaddr)mlayout->mem[i].start; search_end = (zaddr)mlayout->mem[i].end; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/linux/memory-utils-linux.c b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/linux/memory-utils-linux.c index 9c5c60e2b..6ad056a23 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/linux/memory-utils-linux.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/linux/memory-utils-linux.c @@ -80,8 +80,8 @@ zpointer zz_linux_vm_search_code_cave(zaddr address, zsize range_size, zsize siz MemoryLayout *mlayout = zz_linux_vm_get_memory_layout_via_pid(-1); - for (int i = 0; i < mlayout->size; i++) { - + int i; + for (i = 0; i < mlayout->size; i++) { if (mlayout->mem[i].flags == (1 << 0 | 1 << 2)) { search_start = (zaddr)mlayout->mem[i].start; search_end = (zaddr)mlayout->mem[i].end; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/posix/thread-utils-posix.c b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/posix/thread-utils-posix.c index 04c048eaa..151b22d62 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/posix/thread-utils-posix.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/zzdeps/posix/thread-utils-posix.c @@ -35,8 +35,8 @@ zbool zz_posix_thread_add_thread_local_key(ThreadLocalKeyList *keylist, ThreadLo return FALSE; if (keylist->size >= keylist->capacity) { - ThreadLocalKey **keys_tmp = (ThreadLocalKey **)realloc( - keylist->keys, sizeof(ThreadLocalKey *) * keylist->capacity * 2); + ThreadLocalKey **keys_tmp = + (ThreadLocalKey **)realloc(keylist->keys, sizeof(ThreadLocalKey *) * keylist->capacity * 2); if (!keys_tmp) return FALSE; keylist->keys = keys_tmp; @@ -65,9 +65,11 @@ zpointer zz_posix_thread_new_thread_local_key_ptr() { zpointer zz_posix_thread_get_current_thread_data(zpointer key_ptr) { ThreadLocalKeyList *g_keys = g_thread_local_key_list; + zsize i; + if (!key_ptr) return NULL; - for (zsize i = 0; i < g_keys->size; i++) { + for (i = 0; i < g_keys->size; i++) { if (g_keys->keys[i] == key_ptr) return (zpointer)pthread_getspecific(g_keys->keys[i]->key); } @@ -76,8 +78,9 @@ zpointer zz_posix_thread_get_current_thread_data(zpointer key_ptr) { zbool zz_posix_thread_set_current_thread_data(zpointer key_ptr, zpointer data) { ThreadLocalKeyList *g_keys = g_thread_local_key_list; + zsize i; - for (zsize i = 0; i < g_keys->size; i++) { + for (i = 0; i < g_keys->size; i++) { if (g_keys->keys[i] == key_ptr) return pthread_setspecific(g_keys->keys[i]->key, data); } diff --git a/VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/makefile b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/makefile new file mode 100644 index 000000000..a4a8203f0 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/makefile @@ -0,0 +1,19 @@ +NO_COLOR=\x1b[0m +OK_COLOR=\x1b[32;01m +ERROR_COLOR=\x1b[31;01m +WARN_COLOR=\x1b[33;01m + + +HOOKZZ_INCLUDE_DIR := -I$(abspath ../../include) -I$(abspath ../../src) +HOOKZZ_LIB_DIR := -L$(abspath ../../build/ios-armv7) + +ZZ_GCC_TEST := $(shell xcrun --sdk iphoneos --find clang) -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -arch armv7 -O0 -g + +# -undefined dynamic_lookup +test: + @$(ZZ_GCC_TEST) $(HOOKZZ_INCLUDE_DIR) -c test_insn_fix.c -o test_insn_fix.o + @$(ZZ_GCC_TEST) -dynamiclib $(HOOKZZ_LIB_DIR) -lhookzz.static test_insn_fix.o -o test_insn_fix.dylib + @echo "$(OK_COLOR)build [test_insn_fix.dylib] success for armv7! $(NO_COLOR)" +clean: + rm -rf test_insn_fix.o + rm -rf test_insn_fix.dylib diff --git a/VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/test_insn_fix.c b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/test_insn_fix.c new file mode 100644 index 000000000..26069eb60 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-insn-fix/test_insn_fix.c @@ -0,0 +1,106 @@ +#include "hookzz.h" +#include +#include + +static void thumb_insn_need_fix() { + __asm__ volatile(".code 16\n" + + "add r0, pc\n" + + "ldr r0, [pc, #8]\n" + "ldr.W r0, [pc, #8]\n" + + "adr r0, #8\n" + "adr.W r0, #8\n" + "adr.W r0, #-8\n" + + "beq #8\n" + "b #8\n" + "beq.W #8\n" + "b.W #8\n" + + "bl #8\n" + "blx #8\n" + "nop"); +} + +#include "platforms/backend-arm64/interceptor-arm64.h" +#include + +#if 1 +__attribute__((constructor)) void test_insn_fix_thumb() { + + ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); + zbyte temp_code_slice_data[256] = {0}; + + zz_arm_writer_init(&backend->arm_writer, NULL); + zz_arm_relocator_init(&backend->arm_relocator, NULL, &backend->arm_writer); + zz_thumb_writer_init(&backend->thumb_writer, NULL); + zz_thumb_relocator_init(&backend->thumb_relocator, NULL, &backend->thumb_writer); + + ZzThumbRelocator *thumb_relocator; + ZzThumbWriter *thumb_writer; + thumb_relocator = &backend->thumb_relocator; + thumb_writer = &backend->thumb_writer; + + zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + zz_thumb_relocator_reset(thumb_relocator, (zpointer)((zaddr)thumb_insn_need_fix & ~(zaddr)1), thumb_writer); + zsize tmp_relocator_insn_size = 0; + + do { + zz_thumb_relocator_read_one(thumb_relocator, NULL); + zz_thumb_relocator_write_one(thumb_relocator); + tmp_relocator_insn_size = thumb_relocator->input_cur - thumb_relocator->input_start; + } while (tmp_relocator_insn_size < 36); +} +#endif + +#if 0 +__attribute__((__naked__)) void arm_insn_need_fix() { + __asm__ volatile(".arm\n" + "add r0, pc, r0\n" + + "ldr r0, [pc, #8]\n" + + "adr r0, #8\n" + "adr r0, #-8\n" + + "beq #8\n" + "b #8\n" + + "bl #8\n" + "blx #8\n" + "nop"); +} + +#include "platforms/backend-arm/interceptor-arm.h" +#include + +__attribute__((constructor)) void test_insn_fix_arm() { + + ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); + zbyte temp_code_slice_data[256] = {0}; + + zz_arm_writer_init(&backend->arm_writer, NULL); + zz_arm_relocator_init(&backend->arm_relocator, NULL, &backend->arm_writer); + zz_thumb_writer_init(&backend->thumb_writer, NULL); + zz_thumb_relocator_init(&backend->thumb_relocator, NULL, &backend->thumb_writer); + + ZzArmRelocator *arm_relocator; + ZzArmWriter *arm_writer; + arm_relocator = &backend->arm_relocator; + arm_writer = &backend->arm_writer; + + zz_arm_writer_reset(arm_writer, temp_code_slice_data); + + zz_arm_relocator_reset(arm_relocator, (zpointer)((zaddr)arm_insn_need_fix & ~(zaddr)1), arm_writer); + zsize tmp_relocator_insn_size = 0; + + do { + zz_arm_relocator_read_one(arm_relocator, NULL); + zz_arm_relocator_write_one(arm_relocator); + tmp_relocator_insn_size = arm_relocator->input_cur - arm_relocator->input_start; + } while (tmp_relocator_insn_size < 36); +} +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/makefile b/VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/makefile new file mode 100644 index 000000000..5974da54e --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/makefile @@ -0,0 +1,19 @@ +NO_COLOR=\x1b[0m +OK_COLOR=\x1b[32;01m +ERROR_COLOR=\x1b[31;01m +WARN_COLOR=\x1b[33;01m + + +HOOKZZ_INCLUDE_DIR := -I$(abspath ../../include) -I$(abspath ../../src) +HOOKZZ_LIB_DIR := -L$(abspath ../../build/ios-arm64) + +ZZ_GCC_TEST := $(shell xcrun --sdk iphoneos --find clang) -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -arch arm64 -O0 -g + +# -undefined dynamic_lookup +test: + @$(ZZ_GCC_TEST) $(HOOKZZ_INCLUDE_DIR) -c test_insn_fix.c -o test_insn_fix.o + @$(ZZ_GCC_TEST) -dynamiclib $(HOOKZZ_LIB_DIR) -lhookzz.static test_insn_fix.o -o test_insn_fix.dylib + @echo "$(OK_COLOR)build [test_insn_fix.dylib] success for arm64! $(NO_COLOR)" +clean: + rm -rf test_insn_fix.o + rm -rf test_insn_fix.dylib diff --git a/VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/test_insn_fix.c b/VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/test_insn_fix.c new file mode 100644 index 000000000..e2e793d9e --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/tests/arm64-insn-fix/test_insn_fix.c @@ -0,0 +1,40 @@ +#include "hookzz.h" +#include +#include + +static void arm64_insn_need_fix() { + __asm__ volatile("bl #40\n" + "nop"); +} + +#include "platforms/backend-arm64/interceptor-arm64.h" +#include + +#if 1 +__attribute__((constructor)) void test_insn_fix_arm64() { + + ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); + zbyte temp_code_slice_data[256] = {0}; + + zz_arm64_writer_init(&backend->arm64_writer, NULL); + zz_arm64_relocator_init(&backend->arm64_relocator, NULL, &backend->arm64_writer); + zz_arm64_writer_init(&backend->arm64_writer, NULL); + zz_arm64_relocator_init(&backend->arm64_relocator, NULL, &backend->arm64_writer); + + ZzArm64Relocator *arm64_relocator; + ZzArm64Writer *arm64_writer; + arm64_relocator = &backend->arm64_relocator; + arm64_writer = &backend->arm64_writer; + + zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); + + zz_arm64_relocator_reset(arm64_relocator, (zpointer)((zaddr)arm64_insn_need_fix & ~(zaddr)1), arm64_writer); + zsize tmp_relocator_insn_size = 0; + + do { + zz_arm64_relocator_read_one(arm64_relocator, NULL); + zz_arm64_relocator_write_one(arm64_relocator); + tmp_relocator_insn_size = arm64_relocator->input_cur - arm64_relocator->input_start; + } while (tmp_relocator_insn_size < 36); +} +#endif From e69310d780c1ef2dba80208dee2c7912be754602 Mon Sep 17 00:00:00 2001 From: asLody Date: Sun, 12 Nov 2017 14:28:17 +0800 Subject: [PATCH 010/334] [native] : fix crash on Android 5.1. [java] : fix anr problem on BroadcastSystem. --- .../virtual/server/am/BroadcastSystem.java | 18 +++++- VirtualApp/lib/src/main/jni/HookZz/.gitignore | 60 +++++++++++++++++++ .../lib/src/main/jni/HookZz/.gitmodules | 3 + VirtualApp/lib/src/main/jni/HookZz/README.md | 2 +- .../lib/src/main/jni/HookZz/src/interceptor.c | 16 +++-- .../lib/src/main/jni/HookZz/src/interceptor.h | 1 - .../src/platforms/arch-arm/relocator-arm.c | 4 ++ .../src/platforms/arch-arm/relocator-thumb.c | 31 ++++++---- .../src/platforms/arch-arm/writer-arm.c | 26 ++++---- .../src/platforms/arch-arm/writer-thumb.c | 49 ++++++++------- .../src/platforms/arch-arm/writer-thumb.h | 4 +- .../src/platforms/arch-arm64/writer-arm64.c | 27 +++++---- .../platforms/backend-arm/interceptor-arm.c | 32 ++++++---- .../src/platforms/backend-arm/thunker-arm.c | 31 +++++++--- .../backend-arm64/interceptor-arm64.c | 11 +++- .../lib/src/main/jni/HookZz/src/stack.c | 1 + .../main/jni/HookZz/tests/arm-ios/makefile | 6 ++ 17 files changed, 234 insertions(+), 88 deletions(-) create mode 100644 VirtualApp/lib/src/main/jni/HookZz/.gitignore create mode 100644 VirtualApp/lib/src/main/jni/HookZz/.gitmodules diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java index d6f701aaf..10e285e5f 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java @@ -8,7 +8,9 @@ import android.content.pm.ActivityInfo; import android.os.Build; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; +import android.os.Looper; import android.os.Message; import com.lody.virtual.client.core.VirtualCore; @@ -61,8 +63,12 @@ private BroadcastSystem(Context context, VActivityManagerService ams, VAppManage this.mContext = context; this.mApp = app; this.mAMS = ams; - mScheduler = new StaticScheduler(); - mTimeoutHandler = new TimeoutHandler(); + HandlerThread broadcastThread = new HandlerThread("BroadcastThread"); + HandlerThread anrThread = new HandlerThread("BroadcastAnrThread"); + broadcastThread.start(); + anrThread.start(); + mScheduler = new StaticScheduler(broadcastThread.getLooper()); + mTimeoutHandler = new TimeoutHandler(anrThread.getLooper()); fuckHuaWeiVerifier(); } @@ -198,6 +204,9 @@ void broadcastSent(int vuid, ActivityInfo receiverInfo, PendingResultData res) { private static final class StaticScheduler extends Handler { + StaticScheduler(Looper looper) { + super(looper); + } } private static final class BroadcastRecord { @@ -213,6 +222,11 @@ private static final class BroadcastRecord { } private final class TimeoutHandler extends Handler { + + TimeoutHandler(Looper looper) { + super(looper); + } + @Override public void handleMessage(Message msg) { IBinder token = (IBinder) msg.obj; diff --git a/VirtualApp/lib/src/main/jni/HookZz/.gitignore b/VirtualApp/lib/src/main/jni/HookZz/.gitignore new file mode 100644 index 000000000..93f0552df --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/.gitignore @@ -0,0 +1,60 @@ +.DS_Store +build/ +darwin.ios.release.mk +.idea/ +.vscode/ +cmake-build-debug/ +MachoParser.xcworkspace/ + +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/VirtualApp/lib/src/main/jni/HookZz/.gitmodules b/VirtualApp/lib/src/main/jni/HookZz/.gitmodules new file mode 100644 index 000000000..20dc32052 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tools/deps/MachoParser"] + path = tools/deps/MachoParser + url = https://github.com/jmpews/MachoParser.git diff --git a/VirtualApp/lib/src/main/jni/HookZz/README.md b/VirtualApp/lib/src/main/jni/HookZz/README.md index 8e48d5555..c14c9889f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/README.md +++ b/VirtualApp/lib/src/main/jni/HookZz/README.md @@ -10,7 +10,7 @@ ref to: [frida-gum](https://github.com/frida/frida-gum) and [minhook](https://gi # Features -- **inlinehook without Jailbreak [new-90%]** +- **solidify inlinehook without Jailbreak [new-90%]** - **GOT hook with HookZz(i.e. change fishhook to inlinehook), better for APM [new-0%]** diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c index 10464951a..53b81d2a8 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c @@ -18,6 +18,7 @@ #include "interceptor.h" #include "trampoline.h" +#include #define ZZHOOKENTRIES_DEFAULT 100 ZzInterceptor *g_interceptor = NULL; @@ -29,10 +30,14 @@ ZzInitializeInterceptor(void) { if (NULL == interceptor) { interceptor = (ZzInterceptor *)malloc(sizeof(ZzInterceptor)); + memset(interceptor, 0, sizeof(ZzInterceptor)); + hook_function_entry_set = &(interceptor->hook_function_entry_set); hook_function_entry_set->capacity = ZZHOOKENTRIES_DEFAULT; hook_function_entry_set->entries = (ZzHookFunctionEntry **)malloc(sizeof(ZzHookFunctionEntry *) * hook_function_entry_set->capacity); + memset(hook_function_entry_set->entries, 0, sizeof(ZzHookFunctionEntry *) * hook_function_entry_set->capacity); + if (!hook_function_entry_set->entries) { return ZZ_FAILED; } @@ -93,27 +98,24 @@ void ZzInitializeHookFunctionEntry(ZzHookFunctionEntry *entry, int hook_type, zp ZzInterceptor *interceptor = g_interceptor; ZzHookFunctionEntrySet *hook_function_entry_set = &(interceptor->hook_function_entry_set); + memset(entry, 0, sizeof(ZzHookFunctionEntry)); + entry->hook_type = hook_type; entry->id = hook_function_entry_set->size; entry->isEnabled = 0; entry->try_near_jump = try_near_jump; entry->interceptor = interceptor; - entry->target_ptr = target_ptr; entry->target_end_ptr = target_end_ptr; - entry->replace_call = replace_call; entry->pre_call = (zpointer)pre_call; entry->half_call = (zpointer)half_call; entry->post_call = (zpointer)post_call; - entry->on_enter_trampoline = NULL; entry->on_invoke_trampoline = NULL; entry->on_half_trampoline = NULL; entry->on_leave_trampoline = NULL; - entry->origin_prologue.address = target_ptr; - entry->thread_local_key = ZzThreadNewThreadLocalKeyPtr(); /* key function */ @@ -149,6 +151,8 @@ ZZSTATUS ZzBuildHook(zpointer target_ptr, zpointer replace_call_ptr, zpointer *o } entry = (ZzHookFunctionEntry *)malloc(sizeof(ZzHookFunctionEntry)); + memset(entry, 0, sizeof(ZzHookFunctionEntry)); + ZzInitializeHookFunctionEntry(entry, HOOK_FUNCTION_TYPE, target_ptr, 0, replace_call_ptr, pre_call_ptr, NULL, post_call_ptr, try_near_jump); @@ -187,6 +191,8 @@ ZZSTATUS ZzBuildHookAddress(zpointer target_start_ptr, zpointer target_end_ptr, } entry = (ZzHookFunctionEntry *)malloc(sizeof(ZzHookFunctionEntry)); + memset(entry, 0, sizeof(ZzHookFunctionEntry)); + ZzInitializeHookFunctionEntry(entry, HOOK_ADDRESS_TYPE, target_start_ptr, target_end_ptr, NULL, pre_call_ptr, half_call_ptr, NULL, try_near_jump); diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.h b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.h index fa729c5f2..92c26fb57 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.h @@ -50,7 +50,6 @@ struct _ZzInterceptor; struct _ZzHookFunctionEntryBackend; typedef struct _ZzHookFunctionEntry { int hook_type; - zbool isNearJump; unsigned long id; zbool isEnabled; zbool try_near_jump; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c index f5cd99119..e48372f1f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c @@ -22,6 +22,9 @@ #define MAX_RELOCATOR_INSTRUCIONS_SIZE 64 void zz_arm_relocator_init(ZzArmRelocator *relocator, zpointer input_code, ZzArmWriter *output) { + + memset(relocator, 0, sizeof(ZzArmRelocator)); + relocator->inpos = 0; relocator->outpos = 0; relocator->input_start = input_code; @@ -42,6 +45,7 @@ void zz_arm_relocator_init(ZzArmRelocator *relocator, zpointer input_code, ZzArm } void zz_arm_relocator_reset(ZzArmRelocator *self, zpointer input_code, ZzArmWriter *output) { + self->input_cur = input_code; self->input_start = input_code; self->input_pc = (zaddr)input_code; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c index c5fb32259..f56f71f5e 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-thumb.c @@ -22,6 +22,9 @@ #define MAX_RELOCATOR_INSTRUCIONS_SIZE 64 void zz_thumb_relocator_init(ZzThumbRelocator *relocator, zpointer input_code, ZzThumbWriter *output) { + + memset(relocator, 0, sizeof(ZzThumbRelocator)); + relocator->inpos = 0; relocator->outpos = 0; relocator->input_start = input_code; @@ -68,7 +71,7 @@ zsize zz_thumb_relocator_read_one(ZzThumbRelocator *self, ZzInstruction *instruc self->inpos++; if (instruction != NULL) - instruction = insn_ctx; + *instruction = *insn_ctx; self->input_cur += insn_ctx->size; self->input_pc += insn_ctx->size; @@ -143,7 +146,6 @@ void zz_thumb_relocator_write_all(ZzThumbRelocator *self) { zuint count = 0; zuint outpos = self->outpos; ZzThumbWriter thumb_writer = *self->output; - while (zz_thumb_relocator_write_one(self)) count++; } @@ -176,13 +178,19 @@ static zbool zz_thumb_relocator_rewrite_CBNZ_CBZ(ZzThumbRelocator *self, const Z if ((zaddr)self->output->pc % 4) { zz_thumb_writer_put_nop(self->output); } - zz_thumb_writer_put_instruction(self->output, (insn1 & 0b1111110100000111) | 0); - zz_thumb_writer_put_b_imm(self->output, 0x6); + zz_thumb_writer_put_b_imm(self->output, 0x6); ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); zz_thumb_writer_put_ldr_reg_relocate_address(self->output, ZZ_ARM_REG_PC, target_address + 1, literal_insn_ptr); - // zz_thumb_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address + 1); + + // zz_thumb_writer_put_b_imm(self->output, 0x10); + // zz_thumb_writer_put_push_reg(self->output, ZZ_ARM_REG_R0); + // zz_thumb_writer_put_push_reg(self->output, ZZ_ARM_REG_R0); + // zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_R0, target_address + 1); + // zz_thumb_writer_put_str_reg_reg_offset(self->output, ZZ_ARM_REG_R0, ZZ_ARM_REG_SP, 4); + // zz_thumb_writer_put_pop_reg(self->output, ZZ_ARM_REG_R0); + // zz_thumb_writer_put_pop_reg(self->output, ZZ_ARM_REG_PC); return TRUE; } @@ -201,15 +209,10 @@ static zbool zz_thumb_relocator_rewrite_ADD_register_T2(ZzThumbRelocator *self, return FALSE; } - // push R7 - zz_thumb_writer_put_push_reg(self->output, 1 << 7); - // zz_thumb_writer_put_str_index_reg_reg_offset(self->output, ZZ_ARM_REG_R7, ZZ_ARM_REG_SP, -4, 1); + zz_thumb_writer_put_push_reg(self->output, ZZ_ARM_REG_R7); zz_thumb_writer_put_ldr_b_reg_address(self->output, ZZ_ARM_REG_R7, insn_ctx->pc); zz_thumb_writer_put_instruction(self->output, (insn1 & 0b1111111110000111) | ZZ_ARM_REG_R7 << 3); - // zz_thumb_writer_put_add_reg_reg_reg(self->output, Rd_ndx, Rd_ndx, ZZ_ARM_REG_R7); - // pop R7 - zz_thumb_writer_put_pop_reg(self->output, 1 << 7); - // zz_thumb_writer_put_ldr_index_reg_reg_offset(self->output, ZZ_ARM_REG_R7, ZZ_ARM_REG_SP, 4, 0); + zz_thumb_writer_put_pop_reg(self->output, ZZ_ARM_REG_R7); return TRUE; } @@ -222,8 +225,10 @@ zbool zz_thumb_relocator_rewrite_LDR_literal_T1(ZzThumbRelocator *self, const Zz zuint32 imm32 = imm8 << 2; zaddr target_address = ALIGN_4(insn_ctx->pc) + imm32; int Rt_ndx = get_insn_sub(insn1, 8, 3); + zz_thumb_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); zz_thumb_writer_put_ldr_reg_reg_offset(self->output, Rt_ndx, Rt_ndx, 0); + return TRUE; } @@ -246,6 +251,7 @@ zbool zz_thumb_relocator_rewrite_LDR_literal_T2(ZzThumbRelocator *self, const Zz zz_thumb_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); zz_thumb_writer_put_ldr_reg_reg_offset(self->output, Rt_ndx, Rt_ndx, 0); + return TRUE; } @@ -291,6 +297,7 @@ zbool zz_thumb_relocator_rewrite_ADR_T3(ZzThumbRelocator *self, const ZzInstruct zaddr target_address; target_address = insn_ctx->pc + imm32; int Rt_ndx = get_insn_sub(insn_ctx->insn2, 8, 4); + zz_thumb_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); return TRUE; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c index 1e43a6a20..d9883eddf 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-arm.c @@ -24,26 +24,32 @@ ZzArmWriter *zz_arm_writer_new(zpointer data_ptr) { ZzArmWriter *writer = (ZzArmWriter *)malloc(sizeof(ZzArmWriter)); - int t = 4 - (zaddr)data_ptr % 4; + memset(writer, 0, sizeof(ZzArmWriter)); - writer->codedata = data_ptr + t; - writer->base = data_ptr + t; - writer->pc = (zaddr)data_ptr + t; + zaddr align_address = (zaddr)data_ptr & ~(zaddr)3; + writer->codedata = (zpointer)align_address; + writer->base = (zpointer)align_address; + writer->pc = align_address; writer->size = 0; + + writer->literal_insn_size = 0; + memset(writer->literal_insns, 0, sizeof(ZzLiteralInstruction) * MAX_LITERAL_INSN_SIZE); + return writer; } void zz_arm_writer_init(ZzArmWriter *self, zpointer data_ptr) { zz_arm_writer_reset(self, data_ptr); } void zz_arm_writer_reset(ZzArmWriter *self, zpointer data_ptr) { - int t = (zaddr)data_ptr % 4; - ZzArmWriter tmp = {0}; - *self = tmp; + zaddr align_address = (zaddr)data_ptr & ~(zaddr)3; + self->codedata = (zpointer)align_address; + self->base = (zpointer)align_address; + self->pc = align_address; + + self->literal_insn_size = 0; + memset(self->literal_insns, 0, sizeof(ZzLiteralInstruction) * MAX_LITERAL_INSN_SIZE); - self->codedata = data_ptr + t; - self->base = data_ptr + t; - self->pc = (zaddr)data_ptr + t; self->size = 0; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c index f77d86a50..c55db42fe 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.c @@ -24,27 +24,32 @@ ZzThumbWriter *zz_thumb_writer_new(zpointer data_ptr) { ZzThumbWriter *writer = (ZzThumbWriter *)malloc(sizeof(ZzThumbWriter)); - int t = 4 - (zaddr)data_ptr % 4; + memset(writer, 0, sizeof(ZzThumbWriter)); - writer->codedata = data_ptr + t; - writer->base = data_ptr + t; - writer->pc = (zaddr)data_ptr + t; + zaddr align_address = (zaddr)data_ptr & ~(zaddr)3; + writer->codedata = (zpointer)align_address; + writer->base = (zpointer)align_address; + writer->pc = align_address; writer->size = 0; + + writer->literal_insn_size = 0; + memset(writer->literal_insns, 0, sizeof(ZzLiteralInstruction) * MAX_LITERAL_INSN_SIZE); + return writer; } void zz_thumb_writer_init(ZzThumbWriter *self, zpointer data_ptr) { zz_thumb_writer_reset(self, data_ptr); } void zz_thumb_writer_reset(ZzThumbWriter *self, zpointer data_ptr) { - int t = (zaddr)data_ptr % 4; - - ZzThumbWriter tmp = {0}; - *self = tmp; + zaddr align_address = (zaddr)data_ptr & ~(zaddr)3; - self->codedata = data_ptr + t; - self->base = data_ptr + t; - self->pc = (zaddr)data_ptr + t; + self->codedata = (zpointer)align_address; + self->base = (zpointer)align_address; + self->pc = align_address; self->size = 0; + + self->literal_insn_size = 0; + memset(self->literal_insns, 0, sizeof(ZzLiteralInstruction) * MAX_LITERAL_INSN_SIZE); } zsize zz_thumb_writer_near_jump_range_size() { return ((1 << 23) << 1); } @@ -285,10 +290,6 @@ zbool zz_thumb_writer_put_transfer_reg_reg_offset_T3(ZzThumbWriter *self, ZzThum return FALSE; if (right_offset < (1 << 12)) { - // if (operation == ZZ_THUMB_MEMORY_LOAD && rr.meta == ZZ_ARM_REG_PC && - // (self->pc % 4)) { - // zz_thumb_writer_put_nop(self); - // } if (rr.meta == ZZ_ARM_REG_PC) { zz_thumb_writer_put_ldr_reg_imm(self, left_reg, right_offset); } @@ -428,7 +429,7 @@ void zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, insn = 0x1c00 | sign_mask | (ABS(right_value) << 6) | (left.index << 3) | dst.index; zz_thumb_writer_put_instruction(self, insn); } else if ((left.meta == ZZ_ARM_REG_SP || left.meta == ZZ_ARM_REG_PC) && dst.meta <= ZZ_ARM_REG_R7 && - right_value > 0 && (right_value % 4 != 0) && right_value < (1 << 8)) { + right_value > 0 && (right_value % 4 == 0) && right_value < (1 << 8)) { zuint16 base_mask; if (left.meta == ZZ_ARM_REG_SP) @@ -462,21 +463,25 @@ void zz_thumb_writer_put_sub_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, return; } -void zz_thumb_writer_put_push_reg(ZzThumbWriter *self, zint32 regs) { +void zz_thumb_writer_put_push_reg(ZzThumbWriter *self, ZzARMReg reg) { + ZzArmRegInfo ri; + zz_arm_register_describe(reg, &ri); + zuint16 M, register_list; M = 0; - register_list = regs & 0xFF; - zz_thumb_writer_put_instruction(self, 0b1011010000000000 | M << 8 | register_list); + zz_thumb_writer_put_instruction(self, 0b1011010000000000 | M << 8 | 1 << ri.index); return; } -void zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs) { +void zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, ZzARMReg reg) { + ZzArmRegInfo ri; + zz_arm_register_describe(reg, &ri); + zuint16 P, register_list; P = 0; - register_list = regs & 0xFF; - zz_thumb_writer_put_instruction(self, 0b1011110000000000 | P << 8 | register_list); + zz_thumb_writer_put_instruction(self, 0b1011110000000000 | P << 8 | 1 << ri.index); return; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h index 53704b9c0..a05f03dec 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/writer-thumb.h @@ -76,8 +76,8 @@ void zz_thumb_writer_put_add_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint void zz_thumb_writer_put_sub_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, zint32 imm); void zz_thumb_writer_put_add_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, zint32 right_value); void zz_thumb_writer_put_sub_reg_reg_imm(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, zint32 right_value); -void zz_thumb_writer_put_push_reg(ZzThumbWriter *self, zint32 regs); -void zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, zint32 regs); +void zz_thumb_writer_put_push_reg(ZzThumbWriter *self, ZzARMReg reg); +void zz_thumb_writer_put_pop_reg(ZzThumbWriter *self, ZzARMReg reg); void zz_thumb_writer_put_add_reg_reg_reg(ZzThumbWriter *self, ZzARMReg dst_reg, ZzARMReg left_reg, ZzARMReg right_reg); ZzLiteralInstruction *zz_thumb_writer_put_ldr_reg_relocate_address(ZzThumbWriter *self, ZzARMReg reg, zaddr address, ZzLiteralInstruction **literal_insn_ptr); diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c index ab7dcfc74..ae1ec1353 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/writer-arm64.c @@ -30,27 +30,32 @@ ZzArm64Writer *zz_arm64_writer_new(zpointer data_ptr) { ZzArm64Writer *writer = (ZzArm64Writer *)malloc(sizeof(ZzArm64Writer)); - int t = 4 - (zaddr)data_ptr % 4; + memset(writer, 0, sizeof(ZzArm64Writer)); - writer->codedata = data_ptr + t; - writer->base = data_ptr + t; - writer->pc = (zaddr)data_ptr + t; + zaddr align_address = (zaddr)data_ptr & ~(zaddr)3; + writer->codedata = (zpointer)align_address; + writer->base = (zpointer)align_address; + writer->pc = align_address; writer->size = 0; + + writer->literal_insn_size = 0; + memset(writer->literal_insns, 0, sizeof(ZzLiteralInstruction) * MAX_LITERAL_INSN_SIZE); + return writer; } void zz_arm64_writer_init(ZzArm64Writer *self, zpointer target_addr) { zz_arm64_writer_reset(self, target_addr); } void zz_arm64_writer_reset(ZzArm64Writer *self, zpointer data_ptr) { - int t = (zaddr)data_ptr % 4; + zaddr align_address = (zaddr)data_ptr & ~(zaddr)3; - ZzArm64Writer tmp = {0}; - *self = tmp; - - self->codedata = data_ptr + t; - self->base = data_ptr + t; - self->pc = (zaddr)data_ptr + t; + self->codedata = (zpointer)align_address; + self->base = (zpointer)align_address; + self->pc = align_address; self->size = 0; + + self->literal_insn_size = 0; + memset(self->literal_insns, 0, sizeof(ZzLiteralInstruction) * MAX_LITERAL_INSN_SIZE); } // ======= relocator ======= diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c index 9d3b09dde..ee1620f9f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c @@ -25,7 +25,10 @@ #define ZZ_ARM_FULL_REDIRECT_SIZE 8 ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { + ZZSTATUS status; ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); + memset(backend, 0, sizeof(ZzInterceptorBackend)); + backend->allocator = allocator; zz_arm_writer_init(&backend->arm_writer, NULL); @@ -37,7 +40,12 @@ ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { backend->half_thunk = NULL; backend->leave_thunk = NULL; - ZzThunkerBuildThunk(backend); + status = ZzThunkerBuildThunk(backend); + + if (status == ZZ_FAILED) { + ZzInfoLog("%s", "ZzThunkerBuildThunk return ZZ_FAILED\n"); + } + return backend; } @@ -122,10 +130,12 @@ ZzCodeSlice *zz_code_patch_arm_relocate_writer(ZzArmRelocator *arm_relocator, Zz ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zbool is_thumb = FALSE; zaddr target_addr = (zaddr)entry->target_ptr; - zuint redirect_limit; + zuint redirect_limit = 0; ZzArmHookFunctionEntryBackend *entry_backend; entry_backend = (ZzArmHookFunctionEntryBackend *)malloc(sizeof(ZzArmHookFunctionEntryBackend)); + memset(entry_backend, 0, sizeof(ZzArmHookFunctionEntryBackend)); + entry->backend = (struct _ZzHookFunctionEntryBackend *)entry_backend; is_thumb = INSTRUCTION_IS_THUMB((zaddr)entry->target_ptr); @@ -137,10 +147,11 @@ ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *en entry_backend->redirect_code_size = ZZ_THUMB_TINY_REDIRECT_SIZE; } else { zz_thumb_relocator_try_relocate((zpointer)target_addr, ZZ_THUMB_FULL_REDIRECT_SIZE, &redirect_limit); - if (redirect_limit > ZZ_THUMB_TINY_REDIRECT_SIZE && redirect_limit < ZZ_THUMB_FULL_REDIRECT_SIZE) { + if (redirect_limit != 0 && redirect_limit > ZZ_THUMB_TINY_REDIRECT_SIZE && + redirect_limit < ZZ_THUMB_FULL_REDIRECT_SIZE) { entry->try_near_jump = TRUE; entry_backend->redirect_code_size = ZZ_THUMB_TINY_REDIRECT_SIZE; - } else if (redirect_limit < ZZ_THUMB_TINY_REDIRECT_SIZE) { + } else if (redirect_limit != 0 && redirect_limit < ZZ_THUMB_TINY_REDIRECT_SIZE) { return ZZ_FAILED; } else { entry_backend->redirect_code_size = ZZ_THUMB_FULL_REDIRECT_SIZE; @@ -155,10 +166,11 @@ ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *en entry_backend->redirect_code_size = ZZ_ARM_TINY_REDIRECT_SIZE; } else { zz_arm_relocator_try_relocate((zpointer)target_addr, ZZ_ARM_FULL_REDIRECT_SIZE, &redirect_limit); - if (redirect_limit > ZZ_ARM_TINY_REDIRECT_SIZE && redirect_limit < ZZ_ARM_FULL_REDIRECT_SIZE) { + if (redirect_limit != 0 && redirect_limit > ZZ_ARM_TINY_REDIRECT_SIZE && + redirect_limit < ZZ_ARM_FULL_REDIRECT_SIZE) { entry->try_near_jump = TRUE; entry_backend->redirect_code_size = ZZ_ARM_TINY_REDIRECT_SIZE; - } else if (redirect_limit < ZZ_ARM_TINY_REDIRECT_SIZE) { + } else if (redirect_limit != 0 && redirect_limit < ZZ_ARM_TINY_REDIRECT_SIZE) { return ZZ_FAILED; } else { entry_backend->redirect_code_size = ZZ_ARM_FULL_REDIRECT_SIZE; @@ -189,9 +201,7 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti if (is_thumb) { thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); - code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, target_addr, zz_thumb_writer_near_jump_range_size()); if (code_slice) @@ -202,7 +212,6 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti arm_writer = &self->arm_writer; zz_arm_writer_reset(arm_writer, temp_code_slice_data); zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); - code_slice = zz_code_patch_arm_writer(arm_writer, self->allocator, target_addr, zz_arm_writer_near_jump_range_size()); if (code_slice) @@ -328,6 +337,7 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || thumb_relocator->input_cur < target_end_addr); } + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); /* jump to rest target address */ zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)(restore_target_addr + 1)); @@ -337,8 +347,6 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry entry->on_invoke_trampoline = code_slice->data + 1; else return ZZ_FAILED; - - /* set thumb on_invoke_trampoline */ } else { ZzArmRelocator *arm_relocator; ZzArmWriter *arm_writer; @@ -370,6 +378,7 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || arm_relocator->input_cur < target_end_addr); } + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); /* jump to rest target address */ zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)restore_target_addr); @@ -379,7 +388,6 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry entry->on_invoke_trampoline = code_slice->data; else return ZZ_FAILED; - /* set arm on_invoke_trampoline */ } if (entry->hook_type == HOOK_ADDRESS_TYPE) { diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c index 970b5124f..35a87b681 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c @@ -286,17 +286,26 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); zz_thumb_thunker_build_enter_thunk(thumb_writer); - code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) self->enter_thunk = code_slice->data + 1; else return ZZ_FAILED; - /* set thumb enter_thunk */ if (ZzIsEnableDebugMode()) { - char buffer[1024] = {}; + char buffer[2048] = {}; + char thunk_buffer[2048] = {}; + int t = 0; + zpointer p; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); + + for (p = thumb_writer->base; p < thumb_writer->base + thumb_writer->size; p++, t = t + 5) { + sprintf(thunk_buffer + t, "0x%.2x ", *(unsigned char *)p); + } + + ZzInfoLog("%s", thunk_buffer); + // sprintf(buffer + strlen(buffer), "enter_thunk: %s\n", thunk_buffer); + sprintf(buffer + strlen(buffer), "LogInfo: enter_thunk at %p, length: %ld.\n", code_slice->data, code_slice->size); ZzInfoLog("%s", buffer); @@ -304,17 +313,26 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); zz_thumb_thunker_build_leave_thunk(thumb_writer); - code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) self->leave_thunk = code_slice->data + 1; else return ZZ_FAILED; - /* set thumb leave_thunk */ if (ZzIsEnableDebugMode()) { - char buffer[1024] = {}; + char buffer[2048] = {}; + char thunk_buffer[2048] = {}; + int t = 0; + zpointer p; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); + + for (p = thumb_writer->base; p < thumb_writer->base + thumb_writer->size; p++, t = t + 5) { + sprintf(thunk_buffer + t, "0x%.2x ", *(unsigned char *)p); + } + + ZzInfoLog("%s", thunk_buffer); + // sprintf(buffer + strlen(buffer), "enter_thunk: %s\n", thunk_buffer); + sprintf(buffer + strlen(buffer), "LogInfo: leave_thunk at %p, length: %ld.\n", code_slice->data, code_slice->size); ZzInfoLog("%s", buffer); @@ -322,7 +340,6 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); zz_thumb_thunker_build_half_thunk(thumb_writer); - code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) self->half_thunk = code_slice->data + 1; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c index 027745f1f..bbabe79c3 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c @@ -28,6 +28,8 @@ ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { // return backend; } ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); + memset(backend, 0, sizeof(ZzInterceptorBackend)); + backend->allocator = allocator; zz_arm64_writer_init(&backend->arm64_writer, NULL); @@ -79,20 +81,23 @@ ZzCodeSlice *zz_code_patch_arm64_relocate_writer(ZzArm64Relocator *relocator, Zz ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { zaddr target_addr = (zaddr)entry->target_ptr; - zuint redirect_limit; + zuint redirect_limit = 0; ZzArm64HookFunctionEntryBackend *entry_backend; entry_backend = (ZzArm64HookFunctionEntryBackend *)malloc(sizeof(ZzArm64HookFunctionEntryBackend)); + memset(entry_backend, 0, sizeof(ZzArm64HookFunctionEntryBackend)); + entry->backend = (struct _ZzHookFunctionEntryBackend *)entry_backend; if (entry->try_near_jump) { entry_backend->redirect_code_size = ZZ_ARM64_TINY_REDIRECT_SIZE; } else { zz_arm64_relocator_try_relocate((zpointer)target_addr, ZZ_ARM64_FULL_REDIRECT_SIZE, &redirect_limit); - if (redirect_limit > ZZ_ARM64_TINY_REDIRECT_SIZE && redirect_limit < ZZ_ARM64_FULL_REDIRECT_SIZE) { + if (redirect_limit != 0 && redirect_limit > ZZ_ARM64_TINY_REDIRECT_SIZE && + redirect_limit < ZZ_ARM64_FULL_REDIRECT_SIZE) { entry->try_near_jump = TRUE; entry_backend->redirect_code_size = ZZ_ARM64_TINY_REDIRECT_SIZE; - } else if (redirect_limit < ZZ_ARM64_TINY_REDIRECT_SIZE) { + } else if (redirect_limit != 0 && redirect_limit < ZZ_ARM64_TINY_REDIRECT_SIZE) { return ZZ_FAILED; } else { entry_backend->redirect_code_size = ZZ_ARM64_FULL_REDIRECT_SIZE; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/stack.c b/VirtualApp/lib/src/main/jni/HookZz/src/stack.c index 97ec0e18a..6329b5e28 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/stack.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/stack.c @@ -44,6 +44,7 @@ ZzThreadStack *ZzNewThreadStack(zpointer key_ptr) { ZzCallStack *ZzNewCallStack() { ZzCallStack *callstack; callstack = (ZzCallStack *)malloc(sizeof(ZzCallStack)); + callstack->capacity = 4; callstack->items = (ZzCallStackItem *)malloc(sizeof(ZzCallStackItem) * callstack->capacity); diff --git a/VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/makefile b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/makefile index 381c389b5..ed1ac5305 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/makefile +++ b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/makefile @@ -27,6 +27,12 @@ test: @$(ZZ_GCC_TEST) -dynamiclib -Wl,-U,_func -framework Foundation -L$(HOOKZZ_LIB_DIR) -lhookzz.static test_hook_printf.o -o $(HOOKZZ_LIB_DIR)/test_hook_printf.dylib @echo "$(OK_COLOR)build [test_hook_printf.dylib] success for armv7-ios! $(NO_COLOR)" + + @$(ZZ_GCC_TEST) -I$(HOOKZZ_INCLUDE_DIR) -c test_hook_freeaddr.c -o test_hook_freeaddr.o + @$(ZZ_GCC_TEST) -dynamiclib -Wl,-U,_func -framework Foundation -L$(HOOKZZ_LIB_DIR) -lhookzz.static test_hook_freeaddr.o -o $(HOOKZZ_LIB_DIR)/test_hook_freeaddr.dylib + @echo "$(OK_COLOR)build [test_hook_freeaddr.dylib] success for armv7-ios! $(NO_COLOR)" + + @echo "$(OK_COLOR)build [test] success for armv7-ios-hookzz! $(NO_COLOR)" clean: From 92c39afea07d94f2bcfa22d1cbe2f6e1603dc2d6 Mon Sep 17 00:00:00 2001 From: asLody Date: Sun, 19 Nov 2017 13:47:05 +0800 Subject: [PATCH 011/334] [native] : empty implementation of x86. [build] : update gradle version. [build] : remove retrolambda. --- VirtualApp/app/build.gradle | 15 ++- VirtualApp/build.gradle | 5 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- VirtualApp/lib/build.gradle | 4 +- VirtualApp/lib/src/main/jni/Application.mk | 2 +- VirtualApp/lib/src/main/jni/HookZz/Android.mk | 3 + VirtualApp/lib/src/main/jni/HookZz/Makefile | 42 ++++++- .../lib/src/main/jni/HookZz/include/hookzz.h | 5 + .../lib/src/main/jni/HookZz/src/interceptor.c | 15 ++- .../src/platforms/arch-arm/instructions.c | 1 - .../src/platforms/arch-arm/reader-arm.c | 2 - .../src/platforms/arch-arm/relocator-arm.c | 13 +- .../src/platforms/arch-arm64/reader-arm64.c | 34 ------ .../platforms/arch-arm64/relocator-arm64.c | 7 +- .../src/platforms/arch-x86/instructions.c | 2 + .../src/platforms/arch-x86/instructions.h | 31 +++++ .../src/platforms/arch-x86/reader-x86.c | 23 ++++ .../src/platforms/arch-x86/reader-x86.h | 37 ++++++ .../HookZz/src/platforms/arch-x86/regs-x86.c | 21 ++++ .../HookZz/src/platforms/arch-x86/regs-x86.h | 39 ++++++ .../src/platforms/arch-x86/relocator-x86.c | 48 ++++++++ .../src/platforms/arch-x86/relocator-x86.h | 58 +++++++++ .../src/platforms/arch-x86/writer-x86.c | 47 +++++++ .../src/platforms/arch-x86/writer-x86.h | 52 ++++++++ .../platforms/backend-arm/interceptor-arm.c | 67 +++++----- .../src/platforms/backend-arm/thunker-arm.c | 54 +++++++- .../backend-arm64/interceptor-arm64.c | 59 +++++---- .../platforms/backend-arm64/thunker-arm64.c | 44 ++++++- .../backend-x86/interceptor-template-x86.s | 10 ++ .../platforms/backend-x86/interceptor-x86.c | 48 ++++++++ .../platforms/backend-x86/interceptor-x86.h | 54 ++++++++ .../src/platforms/backend-x86/thunker-x86.c | 115 ++++++++++++++++++ .../src/platforms/backend-x86/thunker-x86.h | 35 ++++++ .../lib/src/main/jni/HookZz/src/stack.h | 11 +- .../HookZz/tests/arm-ios/test_hook_freeaddr.c | 70 +++++++++++ 35 files changed, 936 insertions(+), 141 deletions(-) create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.h create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.h create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.h create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.h create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.h create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-template-x86.s create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.h create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.c create mode 100644 VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.h create mode 100644 VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/test_hook_freeaddr.c diff --git a/VirtualApp/app/build.gradle b/VirtualApp/app/build.gradle index acee148a4..d81390460 100644 --- a/VirtualApp/app/build.gradle +++ b/VirtualApp/app/build.gradle @@ -1,10 +1,9 @@ apply plugin: 'com.android.application' -apply plugin: 'me.tatarka.retrolambda' android { compileSdkVersion 25 - buildToolsVersion "25.0.2" + buildToolsVersion '26.0.2' defaultConfig { applicationId "io.virtualapp" minSdkVersion 15 @@ -53,13 +52,13 @@ dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile project(':lib') //Android Lib - compile 'com.android.support:multidex:1.0.1' - compile 'com.android.support:appcompat-v7:25.0.1' + compile 'com.android.support:multidex:1.0.2' + compile 'com.android.support:appcompat-v7:25.4.0' compile 'com.melnykov:floatingactionbutton:1.3.0' - compile 'com.android.support:recyclerview-v7:25.0.1' - compile 'com.android.support:percent:25.0.1' - compile 'com.android.support:design:25.0.1' - compile 'com.android.support:cardview-v7:25.0.1' + compile 'com.android.support:recyclerview-v7:25.4.0' + compile 'com.android.support:percent:25.4.0' + compile 'com.android.support:design:25.4.0' + compile 'com.android.support:cardview-v7:25.4.0' //Promise Support compile 'org.jdeferred:jdeferred-android-aar:1.2.4' // ThirdParty diff --git a/VirtualApp/build.gradle b/VirtualApp/build.gradle index 95d25385a..a9b5ed8ba 100644 --- a/VirtualApp/build.gradle +++ b/VirtualApp/build.gradle @@ -9,9 +9,8 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' - classpath 'me.tatarka:gradle-retrolambda:3.6.0' - classpath 'com.android.tools.build:gradle-experimental:0.8.0' + classpath 'com.android.tools.build:gradle:3.0.0' + classpath 'com.android.tools.build:gradle-experimental:0.11.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/VirtualApp/gradle/wrapper/gradle-wrapper.properties b/VirtualApp/gradle/wrapper/gradle-wrapper.properties index 00a91bd00..074ca5298 100644 --- a/VirtualApp/gradle/wrapper/gradle-wrapper.properties +++ b/VirtualApp/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Jan 15 17:29:32 CST 2017 +#Sun Nov 19 13:36:42 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip diff --git a/VirtualApp/lib/build.gradle b/VirtualApp/lib/build.gradle index d0dd7fa60..8cedbd2d3 100644 --- a/VirtualApp/lib/build.gradle +++ b/VirtualApp/lib/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' android { compileSdkVersion 24 - buildToolsVersion "25.0.2" + buildToolsVersion '26.0.2' defaultConfig { minSdkVersion 14 @@ -11,7 +11,7 @@ android { versionName "1.0" externalNativeBuild { ndkBuild { - abiFilters "armeabi", "armeabi-v7a" + abiFilters "armeabi", "armeabi-v7a", "x86" } } } diff --git a/VirtualApp/lib/src/main/jni/Application.mk b/VirtualApp/lib/src/main/jni/Application.mk index 5e56b2e91..da986993a 100644 --- a/VirtualApp/lib/src/main/jni/Application.mk +++ b/VirtualApp/lib/src/main/jni/Application.mk @@ -1,4 +1,4 @@ -APP_ABI := armeabi armeabi-v7a +APP_ABI := armeabi armeabi-v7a x86 APP_PLATFORM := android-14 APP_STL := gnustl_static APP_OPTIM := release diff --git a/VirtualApp/lib/src/main/jni/HookZz/Android.mk b/VirtualApp/lib/src/main/jni/HookZz/Android.mk index 7c0ff5671..e56863372 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/Android.mk +++ b/VirtualApp/lib/src/main/jni/HookZz/Android.mk @@ -22,6 +22,9 @@ ifeq ($(TARGET_ARCH), arm) else ifeq ($(TARGET_ARCH), arm64) ZZ_SRC += $(wildcard $(LOCAL_PATH)/src/platforms/arch-arm64/*.c) \ $(wildcard $(LOCAL_PATH)/src/platforms/backend-arm64/*.c) +else ifeq ($(TARGET_ARCH), x86) + ZZ_SRC += $(wildcard $(LOCAL_PATH)/src/platforms/arch-x86/*.c) \ + $(wildcard $(LOCAL_PATH)/src/platforms/backend-x86/*.c) endif LOCAL_MODULE := hookzz diff --git a/VirtualApp/lib/src/main/jni/HookZz/Makefile b/VirtualApp/lib/src/main/jni/HookZz/Makefile index 175c71434..a8cd29d72 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/Makefile +++ b/VirtualApp/lib/src/main/jni/HookZz/Makefile @@ -57,6 +57,32 @@ ifeq ($(BACKEND), ios) CFLAGS += -arch $(ZZ_ARCH) + ZZ_GCC_SOURCE := $(ZZ_GCC_BIN) -isysroot $(ZZ_SDK_ROOT) + ZZ_GXX_SOURCE := $(ZZ_GXX_BIN) -isysroot $(ZZ_SDK_ROOT) + ZZ_GCC_TEST := $(ZZ_GCC_BIN) -isysroot $(ZZ_SDK_ROOT) + ZZ_GXX_TEST := $(ZZ_GXX_BIN) -isysroot $(ZZ_SDK_ROOT) +else ifeq ($(BACKEND), macos) + ifeq ($(ARCH), x86) + ZZ_ARCH := i386 + else ifeq ($(ARCH), x86_64) + ZZ_ARCH := x86_64 + endif + + ZZ_BACKEND := macos + ZZ_GXX_BIN := $(shell xcrun --sdk macosx --find clang++) + ZZ_GCC_BIN := $(shell xcrun --sdk macosx --find clang) + ZZ_SDK_ROOT := $(shell xcrun --sdk macosx --show-sdk-path) + ZZ_AR_BIN := $(shell which ar) + ZZ_RANLIB_BIN := $(shell which ranlib) + + ZZ_DEPS_SRCS += $(wildcard $(ZZ_DEPS_PATH)/darwin/*.c) + ZZ_SRCS += $(wildcard $(ZZ_SRCS_PATH)/platforms/backend-darwin/*.c) + + ZZ_CFLAGS := -g -fPIC -shared -dynamiclib + ZZ_DLL := lib$(HOOKZZ_NAME).dylib + + CFLAGS += -arch $(ZZ_ARCH) + ZZ_GCC_SOURCE := $(ZZ_GCC_BIN) -isysroot $(ZZ_SDK_ROOT) ZZ_GXX_SOURCE := $(ZZ_GXX_BIN) -isysroot $(ZZ_SDK_ROOT) ZZ_GCC_TEST := $(ZZ_GCC_BIN) -isysroot $(ZZ_SDK_ROOT) @@ -68,19 +94,27 @@ else ifeq ($(BACKEND), android) ZZ_ARCH := armv7 ZZ_API_LEVEL := android-19 ZZ_CROSS_PREFIX := arm-linux-androideabi- + ZZ_BIN_CROSS_PREFIX := arm-linux-androideabi- else ifeq ($(ARCH), arm64) ZZ_ARCH := arm64 ZZ_API_LEVEL := android-21 ZZ_CROSS_PREFIX := aarch64-linux-android- + ZZ_BIN_CROSS_PREFIX := aarch64-linux-android- + else ifeq ($(ARCH), x86) + ZZ_ARCH := x86 + ZZ_API_LEVEL := android-21 + ZZ_CROSS_PREFIX := x86- + ZZ_BIN_CROSS_PREFIX := i686-linux-android- + endif HOST_DIR := $(shell echo $(HOST) | tr A-Z a-z)-$(HOST_ARCH) ZZ_NDK_HOME := $(shell dirname `which ndk-build`) ZZ_SDK_ROOT := $(ZZ_NDK_HOME)/platforms/$(ZZ_API_LEVEL)/arch-$(ARCH) - ZZ_GCC_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_CROSS_PREFIX)gcc - ZZ_GXX_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_CROSS_PREFIX)g++ - ZZ_AR_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_CROSS_PREFIX)ar - ZZ_RANLIB_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_CROSS_PREFIX)ranlib + ZZ_GCC_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_BIN_CROSS_PREFIX)gcc + ZZ_GXX_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_BIN_CROSS_PREFIX)g++ + ZZ_AR_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_BIN_CROSS_PREFIX)ar + ZZ_RANLIB_BIN := $(ZZ_NDK_HOME)/toolchains/$(ZZ_CROSS_PREFIX)4.9/prebuilt/$(HOST_DIR)/bin/$(ZZ_BIN_CROSS_PREFIX)ranlib ZZ_DEPS_SRCS += $(wildcard $(ZZ_DEPS_PATH)/linux/*.c) ZZ_SRCS += $(wildcard $(ZZ_SRCS_PATH)/platforms/backend-linux/*.c) diff --git a/VirtualApp/lib/src/main/jni/HookZz/include/hookzz.h b/VirtualApp/lib/src/main/jni/HookZz/include/hookzz.h index 9d118699b..34eb953d5 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/include/hookzz.h +++ b/VirtualApp/lib/src/main/jni/HookZz/include/hookzz.h @@ -100,7 +100,12 @@ typedef struct _RegState { zuint32 lr; } RegState; +#elif defined(__i386__) +typedef struct _RegState { +} RegState; #elif defined(__x86_64__) +typedef struct _RegState { +} RegState; #endif #endif diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c index 53b81d2a8..4e513f0c8 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/interceptor.c @@ -15,16 +15,16 @@ */ #include +#include #include "interceptor.h" #include "trampoline.h" -#include +#include "zzinfo.h" #define ZZHOOKENTRIES_DEFAULT 100 ZzInterceptor *g_interceptor = NULL; -ZZSTATUS -ZzInitializeInterceptor(void) { +ZZSTATUS ZzInitializeInterceptor(void) { ZzInterceptor *interceptor = g_interceptor; ZzHookFunctionEntrySet *hook_function_entry_set; @@ -125,6 +125,10 @@ void ZzInitializeHookFunctionEntry(ZzHookFunctionEntry *entry, int hook_type, zp ZZSTATUS ZzBuildHook(zpointer target_ptr, zpointer replace_call_ptr, zpointer *origin_ptr, PRECALL pre_call_ptr, POSTCALL post_call_ptr, zbool try_near_jump) { +#if defined(__i386__) || defined(__x86_64__) + ZzInfoLog("%s", "x86 & x86_64 arch not support"); + return ZZ_FAILED; +#endif ZZSTATUS status = ZZ_DONE_HOOK; ZzInterceptor *interceptor = g_interceptor; @@ -165,7 +169,10 @@ ZZSTATUS ZzBuildHook(zpointer target_ptr, zpointer replace_call_ptr, zpointer *o ZZSTATUS ZzBuildHookAddress(zpointer target_start_ptr, zpointer target_end_ptr, PRECALL pre_call_ptr, HALFCALL half_call_ptr, zbool try_near_jump) { - +#if defined(__i386__) || defined(__x86_64__) + ZzInfoLog("%s", "x86 & x86_64 arch not support"); + return ZZ_FAILED; +#endif ZZSTATUS status = ZZ_DONE_HOOK; ZzInterceptor *interceptor = g_interceptor; ZzHookFunctionEntrySet *hook_function_entry_set = NULL; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c index 4e5588d27..00ec11d1c 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/instructions.c @@ -1,5 +1,4 @@ #include "instructions.h" - #include zuint32 get_insn_sub(zuint32 insn, int start, int length) { return (insn >> start) & ((1 << length) - 1); } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c index a7cdf2807..1274db44f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/reader-arm.c @@ -17,8 +17,6 @@ #include "reader-arm.h" zpointer zz_arm_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer address) { - // ZzInstruction *insn = (ZzInstruction *)malloc(sizeof(ZzInstruction)); - insn_ctx->type = ARM_INSN; insn_ctx->address = (zaddr)address; insn_ctx->pc = (zaddr)address + 8; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c index e48372f1f..ca7c55838 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm/relocator-arm.c @@ -22,9 +22,6 @@ #define MAX_RELOCATOR_INSTRUCIONS_SIZE 64 void zz_arm_relocator_init(ZzArmRelocator *relocator, zpointer input_code, ZzArmWriter *output) { - - memset(relocator, 0, sizeof(ZzArmRelocator)); - relocator->inpos = 0; relocator->outpos = 0; relocator->input_start = input_code; @@ -45,7 +42,6 @@ void zz_arm_relocator_init(ZzArmRelocator *relocator, zpointer input_code, ZzArm } void zz_arm_relocator_reset(ZzArmRelocator *self, zpointer input_code, ZzArmWriter *output) { - self->input_cur = input_code; self->input_start = input_code; self->input_pc = (zaddr)input_code; @@ -185,6 +181,7 @@ static zbool zz_arm_relocator_rewrite_LDR_literal_A1(ZzArmRelocator *self, const zz_arm_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); zz_arm_writer_put_ldr_reg_reg_imm(self->output, Rt_ndx, Rt_ndx, 0); + return TRUE; } @@ -197,7 +194,9 @@ static zbool zz_arm_relocator_rewrite_ADR_A1(ZzArmRelocator *self, const ZzInstr zaddr target_address; target_address = insn_ctx->pc + imm32; int Rt_ndx = get_insn_sub(insn, 12, 4); + zz_arm_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); + return TRUE; } @@ -210,7 +209,9 @@ static zbool zz_arm_relocator_rewrite_ADR_A2(ZzArmRelocator *self, const ZzInstr zaddr target_address; target_address = insn_ctx->pc - imm32; int Rt_ndx = get_insn_sub(insn, 12, 4); + zz_arm_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); + return TRUE; } @@ -232,6 +233,7 @@ static zbool zz_arm_relocator_rewrite_B_A1(ZzArmRelocator *self, const ZzInstruc zz_arm_writer_put_instruction(self->output, (insn & 0xFF000000) | 0); zz_arm_writer_put_b_imm(self->output, 0x4); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); + return TRUE; } @@ -264,8 +266,8 @@ static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A1(ZzArmRelocator *self, c zz_arm_writer_put_instruction(self->output, (insn & 0xF0000000) | 0b1010 << 24 | 0); ZzArmWriter ouput_bak = *self->output; - zz_arm_writer_put_b_imm(self->output, 0); + zz_arm_writer_put_b_imm(self->output, 0); ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); zz_arm_writer_put_ldr_b_reg_relocate_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4, literal_insn_ptr); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); @@ -288,6 +290,7 @@ static zbool zz_arm_relocator_rewrite_BLBLX_immediate_A2(ZzArmRelocator *self, c ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); zz_arm_writer_put_ldr_b_reg_relocate_address(self->output, ZZ_ARM_REG_LR, insn_ctx->pc - 4, literal_insn_ptr); zz_arm_writer_put_ldr_reg_address(self->output, ZZ_ARM_REG_PC, target_address); + return TRUE; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/reader-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/reader-arm64.c index 28a548a83..37c3b4f9a 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/reader-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/reader-arm64.c @@ -18,38 +18,7 @@ #include "zzdeps/common/debugbreak.h" #include "zzdeps/zz.h" -// static csh handle; - -// void zz_arm64_reader_capstone_init(void) { -// cs_err err = 0; - -// err = cs_open(CS_ARCH_ARM6464, CS_MODE_ARM64, &handle); -// if (err) { -// Xerror("Failed on cs_open() with error returned: %u\n", err); -// exit(-1); -// } - -// cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); -// } - -// cs_insn *zz_arm64_reader_disassemble_at(zpointer address) { -// if (!handle) -// zz_arm64_reader_capstone_init(); -// cs_insn *insn; -// size_t count; -// count = cs_disasm(handle, address, 16, (unsigned long)address, 0, &insn); -// if (!insn) { -// #if defined(DEBUG_MODE) -// debug_break(); -// #endif -// Xerror("zz_arm64_reader_disassemble_at error at %p", (zpointer)address); -// } -// return insn; -// } - zpointer zz_arm64_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer address) { - // ZzInstruction *insn = (ZzInstruction *)malloc(sizeof(ZzInstruction)); - insn_ctx->address = (zaddr)address; insn_ctx->size = 4; insn_ctx->pc = (zaddr)address; @@ -58,9 +27,6 @@ zpointer zz_arm64_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer } ARM64InsnType GetARM64InsnType(zuint32 insn) { - zuint32 op, op1; - op1 = get_insn_sub(insn, 20, 5); - // PAGE: C6-673 if (insn_equal(insn, "01011000xxxxxxxxxxxxxxxxxxxxxxxx")) { return ARM64_INS_LDR_literal; diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c index 9f8f99b4d..b64dbd8db 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-arm64/relocator-arm64.c @@ -67,7 +67,7 @@ zsize zz_arm64_relocator_read_one(ZzArm64Relocator *self, ZzInstruction *instruc self->inpos++; if (instruction != NULL) - instruction = insn_ctx; + *instruction = *insn_ctx; self->input_cur += insn_ctx->size; self->input_pc += insn_ctx->size; @@ -156,6 +156,7 @@ static zbool zz_arm64_relocator_rewrite_LDR_literal(ZzArm64Relocator *self, cons zz_arm64_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); zz_arm64_writer_put_ldr_reg_reg_offset(self->output, Rt_ndx, Rt_ndx, 0); + return TRUE; } @@ -172,6 +173,7 @@ static zbool zz_arm64_relocator_rewrite_ADR(ZzArm64Relocator *self, const ZzInst int Rt_ndx = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); + return TRUE; } @@ -189,6 +191,7 @@ static zbool zz_arm64_relocator_rewrite_ADRP(ZzArm64Relocator *self, const ZzIns int Rt_ndx = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_ldr_b_reg_address(self->output, Rt_ndx, target_address); + return TRUE; } @@ -202,7 +205,6 @@ static zbool zz_arm64_relocator_rewrite_B(ZzArm64Relocator *self, const ZzInstru zaddr target_address; target_address = insn_ctx->pc + offset; - int Rt_ndx = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_ldr_br_reg_address(self->output, ZZ_ARM64_REG_X17, target_address); @@ -219,7 +221,6 @@ static zbool zz_arm64_relocator_rewrite_BL(ZzArm64Relocator *self, const ZzInstr zaddr target_address; target_address = insn_ctx->pc + offset; - int Rt_ndx = get_insn_sub(insn, 0, 4); zz_arm64_writer_put_ldr_blr_b_reg_address(self->output, ZZ_ARM64_REG_X17, target_address); ZzLiteralInstruction **literal_insn_ptr = &(self->relocate_literal_insns[self->relocate_literal_insns_size++]); diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.c new file mode 100644 index 000000000..dc09a0d61 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.c @@ -0,0 +1,2 @@ +#include "instructions.h" +#include diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.h new file mode 100644 index 000000000..adc4675f8 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/instructions.h @@ -0,0 +1,31 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef platforms_arch_x86_instructions_h +#define platforms_arch_x86_instructions_h + +#include "hookzz.h" + +typedef struct _ZzInstruction { +} ZzInstruction; + +typedef struct _ZzRelocateInstruction { + const ZzInstruction *insn_ctx; + zaddr relocated_offset; + zsize relocated_length; +} ZzRelocateInstruction; + +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.c new file mode 100644 index 000000000..8185d3ed0 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.c @@ -0,0 +1,23 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reader-x86.h" +#include "zzdeps/common/debugbreak.h" +#include "zzdeps/zz.h" + +zpointer zz_x86_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer address) { return NULL; } + +X86InsnType GetX86InsnType(zuint32 insn) { return X86_UNDEF; } \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.h new file mode 100644 index 000000000..864610be2 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/reader-x86.h @@ -0,0 +1,37 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef platforms_arch_x86_reader_h +#define platforms_arch_x86_reader_h + +// platforms +#include "instructions.h" + +// hookzz + +// zzdeps +#include "hookzz.h" +#include "zzdefs.h" +#include "zzdeps/common/debugbreak.h" +#include "zzdeps/zz.h" + +typedef enum _X86InsnType { X86_UNDEF } X86InsnType; + +X86InsnType GetX86InsnType(zuint32 insn); + +zpointer zz_x86_reader_read_one_instruction(ZzInstruction *insn_ctx, zpointer address); + +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.c new file mode 100644 index 000000000..91af33c98 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.c @@ -0,0 +1,21 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "regs-x86.h" + +void zz_x86_register_describe(ZzX86Reg reg, ZzX86RegInfo *ri) { + +} diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.h new file mode 100644 index 000000000..377ee37a7 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/regs-x86.h @@ -0,0 +1,39 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef platforms_arch_x86_regs_h +#define platforms_arch_x86_regs_h + +// platforms +#include "instructions.h" + +// hookzz + +// zzdeps +#include "hookzz.h" +#include "zzdefs.h" +#include "zzdeps/common/debugbreak.h" +#include "zzdeps/zz.h" + +typedef enum _ZzX86Reg { X86_REG_UNDEF } ZzX86Reg; + +typedef struct _ZzX86RegInfo { + +} ZzX86RegInfo; + +void zz_x86_register_describe(ZzX86Reg reg, ZzX86RegInfo *ri); + +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.c new file mode 100644 index 000000000..3380a97ae --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.c @@ -0,0 +1,48 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "relocator-x86.h" +#include +#include + +#define MAX_RELOCATOR_INSTRUCIONS_SIZE 64 + +void zz_x86_relocator_init(ZzX86Relocator *relocator, zpointer input_code, ZzX86Writer *output) { +} + +void zz_x86_relocator_reset(ZzX86Relocator *self, zpointer input_code, ZzX86Writer *output) { +} + +zsize zz_x86_relocator_read_one(ZzX86Relocator *self, ZzInstruction *instruction) { + return 0; +} + +zaddr zz_x86_relocator_get_insn_relocated_offset(ZzX86Relocator *self, zaddr address) { + return 0; +} + +void zz_x86_relocator_relocate_writer(ZzX86Relocator *relocator, zaddr code_address) { +} + +void zz_x86_relocator_write_all(ZzX86Relocator *self) { +} + +void zz_x86_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes) { +} + +zbool zz_x86_relocator_write_one(ZzX86Relocator *self) { + return TRUE; +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.h new file mode 100644 index 000000000..ed6a1efda --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/relocator-x86.h @@ -0,0 +1,58 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef platforms_arch_x86_relocator_h +#define platforms_arch_x86_relocator_h + +// platforms +#include "instructions.h" +#include "reader-x86.h" +#include "regs-x86.h" +#include "writer-x86.h" + +// hookzz +#include "writer.h" + +// zzdeps +#include "hookzz.h" +#include "zzdefs.h" +#include "zzdeps/common/debugbreak.h" +#include "zzdeps/zz.h" + +typedef struct _ZzX86Relocator { + zbool try_relocated_again; + zsize try_relocated_length; + zpointer input_start; + zpointer input_cur; + zaddr input_pc; + zuint inpos; + zuint outpos; + ZzInstruction *input_insns; + ZzRelocateInstruction *output_insns; + ZzX86Writer *output; + ZzLiteralInstruction **relocate_literal_insns; + zsize relocate_literal_insns_size; +} ZzX86Relocator; + +void zz_x86_relocator_init(ZzX86Relocator *relocator, zpointer input_code, ZzX86Writer *writer); +void zz_x86_relocator_reset(ZzX86Relocator *self, zpointer input_code, ZzX86Writer *output); + +zsize zz_x86_relocator_read_one(ZzX86Relocator *self, ZzInstruction *instruction); +zbool zz_x86_relocator_write_one(ZzX86Relocator *self); +void zz_x86_relocator_write_all(ZzX86Relocator *self); +void zz_x86_relocator_try_relocate(zpointer address, zuint min_bytes, zuint *max_bytes); + +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.c new file mode 100644 index 000000000..eb6afe6c7 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.c @@ -0,0 +1,47 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "writer-x86.h" + +ZzX86Writer *zz_x86_writer_new(zpointer data_ptr) { + return NULL; +} + +void zz_x86_writer_init(ZzX86Writer *self, zpointer target_addr) { zz_x86_writer_reset(self, target_addr); } + +void zz_x86_writer_reset(ZzX86Writer *self, zpointer data_ptr) { +} + +zsize zz_x86_writer_near_jump_range_size() { return 0; } + + +void zz_x86_writer_put_bytes(ZzWriter *self, zbyte *data, zsize size) { + +} + +void zz_x86_writer_put_instruction(ZzWriter *self, zuint32 insn) { + +} + + +// ======= relocator ======= + +// ======= user custom ======= + +// ======= default ======= diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.h new file mode 100644 index 000000000..602921036 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/arch-x86/writer-x86.h @@ -0,0 +1,52 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef platforms_arch_x86_writer_h +#define platforms_arch_x86_writer_h + +// platforms +#include "instructions.h" +#include "regs-x86.h" +#include "writer-x86.h" + +// hookzz +#include "writer.h" + +// zzdeps +#include "hookzz.h" +#include "zzdefs.h" +#include "zzdeps/common/debugbreak.h" +#include "zzdeps/zz.h" + +typedef ZzWriter ZzX86Writer; + +ZzX86Writer *zz_x86_writer_new(zpointer data_ptr); + +void zz_x86_writer_reset(ZzX86Writer *self, zpointer data_ptr); + +void zz_x86_writer_init(ZzX86Writer *self, zpointer target_addr); + +zsize zz_x86_writer_near_jump_range_size(); +void zz_x86_writer_put_bytes(ZzWriter *self, zbyte *data, zsize size); +void zz_x86_writer_put_instruction(ZzWriter *self, zuint32 insn); + +// ======= user custom ======= + +// ======= default ======= + +// ======= relocator ======= + +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c index ee1620f9f..c37bb132f 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/interceptor-arm.c @@ -25,17 +25,19 @@ #define ZZ_ARM_FULL_REDIRECT_SIZE 8 ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { + if (!ZzMemoryIsSupportAllocateRXPage()) { + return NULL; + } ZZSTATUS status; ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); memset(backend, 0, sizeof(ZzInterceptorBackend)); - backend->allocator = allocator; - zz_arm_writer_init(&backend->arm_writer, NULL); zz_arm_relocator_init(&backend->arm_relocator, NULL, &backend->arm_writer); zz_thumb_writer_init(&backend->thumb_writer, NULL); zz_thumb_relocator_init(&backend->thumb_relocator, NULL, &backend->thumb_writer); + backend->allocator = allocator; backend->enter_thunk = NULL; backend->half_thunk = NULL; backend->leave_thunk = NULL; @@ -44,6 +46,7 @@ ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { if (status == ZZ_FAILED) { ZzInfoLog("%s", "ZzThunkerBuildThunk return ZZ_FAILED\n"); + return NULL; } return backend; @@ -201,7 +204,11 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti if (is_thumb) { thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + /* jump to on_enter_trampoline */ zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); + + /* code patch */ code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, target_addr, zz_thumb_writer_near_jump_range_size()); if (code_slice) @@ -211,7 +218,11 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti } else { arm_writer = &self->arm_writer; zz_arm_writer_reset(arm_writer, temp_code_slice_data); + + /* jump to on_enter_trampoline */ zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_enter_trampoline); + + /* code patch */ code_slice = zz_code_patch_arm_writer(arm_writer, self->allocator, target_addr, zz_arm_writer_near_jump_range_size()); if (code_slice) @@ -248,27 +259,25 @@ ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - /* 2 stack space: 1. next_hop 2. entry arg */ + /* prepare 2 stack space: 1. next_hop 2. entry arg */ zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); - /* push r7 */ - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); // push r7 zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); - - /* pop r7 */ - zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); // pop r7 zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); /* jump to enter thunk */ zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->enter_thunk); + /* code patch */ code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) entry->on_enter_trampoline = code_slice->data + 1; else return ZZ_FAILED; + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildEnterTrampoline:"); @@ -331,17 +340,17 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry if (thumb_relocator->input_cur >= target_end_addr && !entry->target_half_ret_addr) { /* jump to rest target address */ zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_half_trampoline); - entry->target_half_ret_addr = (zpointer)(thumb_writer->size + 1); } } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || thumb_relocator->input_cur < target_end_addr); } - restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); /* jump to rest target address */ + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)(restore_target_addr + 1)); + /* code patch */ code_slice = zz_code_patch_thumb_relocate_writer(thumb_relocator, thumb_writer, self->allocator, 0, 0); if (code_slice) entry->on_invoke_trampoline = code_slice->data + 1; @@ -372,17 +381,17 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry if (arm_relocator->input_cur >= target_end_addr && !entry->target_half_ret_addr) { /* jump to rest target address */ zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)entry->on_half_trampoline); - entry->target_half_ret_addr = (zpointer)arm_writer->size; } } while (tmp_relocator_insn_size < entry_backend->redirect_code_size || arm_relocator->input_cur < target_end_addr); } - restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); /* jump to rest target address */ + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); zz_arm_writer_put_ldr_reg_address(arm_writer, ZZ_ARM_REG_PC, (zaddr)restore_target_addr); + /* code patch */ code_slice = zz_code_patch_arm_relocate_writer(arm_relocator, arm_writer, self->allocator, 0, 0); if (code_slice) entry->on_invoke_trampoline = code_slice->data; @@ -390,11 +399,12 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry return ZZ_FAILED; } + /* update target_half_ret_addr */ if (entry->hook_type == HOOK_ADDRESS_TYPE) { - // update target_half_ret_addr entry->target_half_ret_addr += (zaddr)code_slice->data; } + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildInvokeTrampoline:"); @@ -444,26 +454,23 @@ ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry * thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - /* 2 stack space: 1. next_hop 2. entry arg */ + /* prepare 2 stack space: 1. next_hop 2. entry arg */ zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); - /* push r7 */ - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); // push r7 zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); - - /* pop r7 */ - zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); // pop r7 zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); + /* jump to half_thunk */ zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->half_thunk); + /* code patch */ code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) entry->on_half_trampoline = code_slice->data + 1; else return ZZ_FAILED; - /* set thumb on_half_trampoline */ free(code_slice); return status; @@ -479,27 +486,25 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); - /* 2 stack space: 1. next_hop 2. entry arg */ + /* prepare 2 stack space: 1. next_hop 2. entry arg */ zz_thumb_writer_put_sub_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0xc); - /* push r7 */ - zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); - + zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); // push r7 zz_thumb_writer_put_ldr_b_reg_address(thumb_writer, ZZ_ARM_REG_R1, (zaddr)entry); zz_thumb_writer_put_str_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); - - /* pop r7 */ - zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); + zz_thumb_writer_put_ldr_reg_reg_offset(thumb_writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x0); // pop r7 zz_thumb_writer_put_add_reg_imm(thumb_writer, ZZ_ARM_REG_SP, 0x4); + /* jump to leave_thunk */ zz_thumb_writer_put_ldr_reg_address(thumb_writer, ZZ_ARM_REG_PC, (zaddr)self->leave_thunk); + /* code patch */ code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) entry->on_leave_trampoline = code_slice->data + 1; else return ZZ_FAILED; - /* set thumb on_leave_trampoline */ + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildLeaveTrampoline:"); @@ -509,6 +514,7 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzInfoLog("%s", buffer); } + free(code_slice); return ZZ_DONE; } @@ -525,7 +531,6 @@ ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *e target_addr = (zaddr)entry->target_ptr & ~(zaddr)1; if (is_thumb) { - ZzThumbWriter *thumb_writer; thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c index 35a87b681..51529186d 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm/thunker-arm.c @@ -89,20 +89,22 @@ void function_context_begin_invocation(ZzHookFunctionEntry *entry, zpointer next zpointer caller_ret_addr) { Xdebug("target %p call begin-invocation", entry->target_ptr); + ZzThreadStack *threadstack = ZzGetCurrentThreadStack(entry->thread_local_key); if (!threadstack) { threadstack = ZzNewThreadStack(entry->thread_local_key); } - ZzCallStack *callstack = ZzNewCallStack(); ZzPushCallStack(threadstack, callstack); + /* call pre_call */ if (entry->pre_call) { PRECALL pre_call; pre_call = entry->pre_call; (*pre_call)(rs, (ThreadStack *)threadstack, (CallStack *)callstack); } + /* set next hop */ if (entry->replace_call) { *(zpointer *)next_hop = entry->replace_call; } else { @@ -118,6 +120,7 @@ void function_context_begin_invocation(ZzHookFunctionEntry *entry, zpointer next void function_context_half_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs, zpointer caller_ret_addr) { Xdebug("target %p call half-invocation", entry->target_ptr); + ZzThreadStack *threadstack = ZzGetCurrentThreadStack(entry->thread_local_key); if (!threadstack) { #if defined(DEBUG_MODE) @@ -126,11 +129,14 @@ void function_context_half_invocation(ZzHookFunctionEntry *entry, zpointer next_ } ZzCallStack *callstack = ZzPopCallStack(threadstack); + /* call half_call */ if (entry->half_call) { HALFCALL half_call; half_call = entry->half_call; (*half_call)(rs, (ThreadStack *)threadstack, (CallStack *)callstack); } + + /* set next hop */ *(zpointer *)next_hop = (zpointer)entry->target_half_ret_addr; ZzFreeCallStack(callstack); @@ -139,6 +145,7 @@ void function_context_half_invocation(ZzHookFunctionEntry *entry, zpointer next_ // just like post_call, wow! void function_context_end_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs) { Xdebug("%p call end-invocation", entry->target_ptr); + ZzThreadStack *threadstack = ZzGetCurrentThreadStack(entry->thread_local_key); if (!threadstack) { #if defined(DEBUG_MODE) @@ -147,11 +154,14 @@ void function_context_end_invocation(ZzHookFunctionEntry *entry, zpointer next_h } ZzCallStack *callstack = ZzPopCallStack(threadstack); + /* call post_call */ if (entry->post_call) { POSTCALL post_call; post_call = entry->post_call; (*post_call)(rs, (ThreadStack *)threadstack, (CallStack *)callstack); } + + /* set next hop */ *(zpointer *)next_hop = callstack->caller_ret_addr; ZzFreeCallStack(callstack); @@ -160,7 +170,6 @@ void function_context_end_invocation(ZzHookFunctionEntry *entry, zpointer next_h void zz_thumb_thunker_build_enter_thunk(ZzWriter *writer) { /* save general registers and sp */ - zz_thumb_writer_put_bx_reg(writer, ZZ_ARM_REG_PC); zz_arm_writer_put_bytes(writer, THUMB_FUNCTION_ADDRESS((void *)ctx_save), 15 * 4); zz_arm_writer_put_add_reg_reg_imm(writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_PC, 1); @@ -186,7 +195,6 @@ void zz_thumb_thunker_build_enter_thunk(ZzWriter *writer) { /* restore general registers and sp */ zz_thumb_writer_put_add_reg_imm(writer, ZZ_ARM_REG_SP, 0x8); - zz_thumb_writer_put_bx_reg(writer, ZZ_ARM_REG_PC); zz_arm_writer_put_bytes(writer, THUMB_FUNCTION_ADDRESS((void *)ctx_restore), 14 * 4); zz_arm_writer_put_bx_to_thumb(writer); @@ -228,7 +236,6 @@ void zz_thumb_thunker_build_half_thunk(ZzWriter *writer) { /* restore general registers and sp */ zz_thumb_writer_put_add_reg_imm(writer, ZZ_ARM_REG_SP, 0x8); - zz_thumb_writer_put_bx_reg(writer, ZZ_ARM_REG_PC); zz_arm_writer_put_bytes(writer, THUMB_FUNCTION_ADDRESS((void *)ctx_restore), 14 * 4); zz_arm_writer_put_bx_to_thumb(writer); @@ -254,8 +261,11 @@ void zz_thumb_thunker_build_leave_thunk(ZzWriter *writer) { zz_thumb_writer_put_str_reg_reg_offset(writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, 0x4); /* pass enter func args */ + /* entry */ zz_thumb_writer_put_ldr_reg_reg_offset(writer, ZZ_ARM_REG_R0, ZZ_ARM_REG_SP, CTX_SAVE_STACK_OFFSET + 0x8); + /* next hop*/ zz_thumb_writer_put_add_reg_reg_imm(writer, ZZ_ARM_REG_R1, ZZ_ARM_REG_SP, CTX_SAVE_STACK_OFFSET + 0x8 + 0x4); + /* RegState */ zz_thumb_writer_put_add_reg_reg_imm(writer, ZZ_ARM_REG_R2, ZZ_ARM_REG_SP, 0x4); /* call function_context_begin_invocation */ @@ -264,7 +274,6 @@ void zz_thumb_thunker_build_leave_thunk(ZzWriter *writer) { /* restore general registers and sp */ zz_thumb_writer_put_add_reg_imm(writer, ZZ_ARM_REG_SP, 0x8); - zz_thumb_writer_put_bx_reg(writer, ZZ_ARM_REG_PC); zz_arm_writer_put_bytes(writer, THUMB_FUNCTION_ADDRESS((void *)ctx_restore), 14 * 4); zz_arm_writer_put_bx_to_thumb(writer); @@ -285,13 +294,18 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { thumb_writer = &self->thumb_writer; zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + /* buid enter_thunk */ zz_thumb_thunker_build_enter_thunk(thumb_writer); + + /* code patch */ code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) self->enter_thunk = code_slice->data + 1; else return ZZ_FAILED; + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[2048] = {}; char thunk_buffer[2048] = {}; @@ -312,13 +326,18 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { } zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + /* build leave_thunk */ zz_thumb_thunker_build_leave_thunk(thumb_writer); + + /* code patch */ code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) self->leave_thunk = code_slice->data + 1; else return ZZ_FAILED; + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[2048] = {}; char thunk_buffer[2048] = {}; @@ -339,11 +358,36 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { } zz_thumb_writer_reset(thumb_writer, temp_code_slice_data); + + /* build half_thunk */ zz_thumb_thunker_build_half_thunk(thumb_writer); + + /* code patch */ code_slice = zz_code_patch_thumb_writer(thumb_writer, self->allocator, 0, 0); if (code_slice) self->half_thunk = code_slice->data + 1; else return ZZ_FAILED; + + /* debug log */ + if (ZzIsEnableDebugMode()) { + char buffer[2048] = {}; + char thunk_buffer[2048] = {}; + int t = 0; + zpointer p; + sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); + + for (p = thumb_writer->base; p < thumb_writer->base + thumb_writer->size; p++, t = t + 5) { + sprintf(thunk_buffer + t, "0x%.2x ", *(unsigned char *)p); + } + + ZzInfoLog("%s", thunk_buffer); + // sprintf(buffer + strlen(buffer), "half_thunk: %s\n", thunk_buffer); + + sprintf(buffer + strlen(buffer), "LogInfo: half_thunk at %p, length: %ld.\n", code_slice->data, + code_slice->size); + ZzInfoLog("%s", buffer); + } + return status; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c index bbabe79c3..3df307a8d 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/interceptor-arm64.c @@ -25,21 +25,26 @@ ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { if (!ZzMemoryIsSupportAllocateRXPage()) { return NULL; - // return backend; } + ZZSTATUS status; + ZzInterceptorBackend *backend = (ZzInterceptorBackend *)malloc(sizeof(ZzInterceptorBackend)); memset(backend, 0, sizeof(ZzInterceptorBackend)); - backend->allocator = allocator; - zz_arm64_writer_init(&backend->arm64_writer, NULL); zz_arm64_relocator_init(&backend->arm64_relocator, NULL, &backend->arm64_writer); + backend->allocator = allocator; backend->enter_thunk = NULL; backend->half_thunk = NULL; backend->leave_thunk = NULL; - ZzThunkerBuildThunk(backend); + status = ZzThunkerBuildThunk(backend); + if (status == ZZ_FAILED) { + ZzInfoLog("%s", "ZzThunkerBuildThunk return ZZ_FAILED\n"); + return NULL; + } + return backend; } @@ -119,9 +124,7 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti 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) @@ -137,6 +140,8 @@ ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFuncti code_slice->data, code_slice->size, entry->on_enter_trampoline); ZzInfoLog("%s", buffer); } + + free(code_slice); return status; } ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { @@ -150,20 +155,22 @@ ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - /* 2 stack space: 1. next_hop 2. entry arg */ + /* 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:"); @@ -177,6 +184,7 @@ ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzBuildEnterTransferTrampoline(self, entry); } + free(code_slice); return status; } @@ -194,7 +202,6 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - zz_arm64_relocator_reset(arm64_relocator, (zpointer)target_addr, arm64_writer); zsize tmp_relocator_insn_size = 0; entry->target_half_ret_addr = 0; @@ -211,7 +218,6 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry zz_arm64_relocator_write_one(arm64_relocator); tmp_relocator_insn_size = arm64_relocator->input_cur - arm64_relocator->input_start; if (arm64_relocator->input_cur >= entry->target_end_ptr && !entry->target_half_ret_addr) { - /* jump to rest target address */ zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry->on_half_trampoline); @@ -221,16 +227,23 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry arm64_relocator->input_cur < entry->target_end_ptr); } - restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); - /* jump to rest target address */ + restore_target_addr = (zpointer)((zaddr)target_addr + tmp_relocator_insn_size); zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)restore_target_addr); - code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); + /* code patch */ + code_slice = zz_code_patch_arm64_relocate_writer(arm64_relocator, arm64_writer, self->allocator, 0, 0); if (code_slice) entry->on_invoke_trampoline = code_slice->data; else return ZZ_FAILED; + + /* update target_half_ret_addr */ + if (entry->hook_type == HOOK_ADDRESS_TYPE) { + entry->target_half_ret_addr += (zaddr)code_slice->data; + } + + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {0}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildInvokeTrampoline:"); @@ -253,10 +266,7 @@ ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzInfoLog("%s", buffer); } - if (entry->hook_type == HOOK_ADDRESS_TYPE) { - // update target_half_ret_addr - entry->target_half_ret_addr += (zaddr)code_slice->data; - } + free(code_slice); return status; } @@ -271,14 +281,15 @@ ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry * arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - /* 2 stack space: 1. next_hop 2. entry arg */ + /* 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; @@ -293,26 +304,27 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzCodeSlice *code_slice = NULL; ZzArm64HookFunctionEntryBackend *entry_backend = (ZzArm64HookFunctionEntryBackend *)entry->backend; zaddr target_addr = (zaddr)entry->target_ptr; - ZzArm64Writer *arm64_writer; + ZzArm64Writer *arm64_writer = NULL; arm64_writer = &self->arm64_writer; zz_arm64_writer_reset(arm64_writer, temp_code_slice_data); - /* 2 stack space: 1. next_hop 2. entry arg */ + /* 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 leave thunk */ zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)self->leave_thunk); + /* code patch */ code_slice = zz_code_patch_arm64_writer(arm64_writer, self->allocator, 0, 0); if (code_slice) entry->on_leave_trampoline = code_slice->data; else return ZZ_FAILED; + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzBuildLeaveTrampoline:"); @@ -322,6 +334,7 @@ ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry ZzInfoLog("%s", buffer); } + free(code_slice); return ZZ_DONE; } @@ -338,7 +351,7 @@ ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *e arm64_writer->pc = target_addr; if (entry_backend->redirect_code_size == ZZ_ARM64_TINY_REDIRECT_SIZE) { - zz_arm64_writer_put_b_imm(arm64_writer, (zaddr)entry->on_enter_transfer_trampoline - (zaddr)target_addr); + zz_arm64_writer_put_b_imm(arm64_writer, (zaddr)entry->on_enter_transfer_trampoline - (zaddr)arm64_writer->pc); } else { zz_arm64_writer_put_ldr_br_reg_address(arm64_writer, ZZ_ARM64_REG_X17, (zaddr)entry->on_enter_trampoline); } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c index 4286563a9..a5b3dc648 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-arm64/thunker-arm64.c @@ -104,22 +104,23 @@ // just like pre_call, wow! void function_context_begin_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs, zpointer caller_ret_addr) { + Xinfo("target %p call begin-invocation", entry->target_ptr); - Xdebug("target %p call begin-invocation", entry->target_ptr); ZzThreadStack *stack = ZzGetCurrentThreadStack(entry->thread_local_key); if (!stack) { stack = ZzNewThreadStack(entry->thread_local_key); } - ZzCallStack *callstack = ZzNewCallStack(); ZzPushCallStack(stack, callstack); + /* call pre_call */ if (entry->pre_call) { PRECALL pre_call; pre_call = entry->pre_call; (*pre_call)(rs, (ThreadStack *)stack, (CallStack *)callstack); } + /* set next hop */ if (entry->replace_call) { *(zpointer *)next_hop = entry->replace_call; } else { @@ -136,6 +137,7 @@ void function_context_begin_invocation(ZzHookFunctionEntry *entry, zpointer next void function_context_half_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs, zpointer caller_ret_addr) { Xdebug("target %p call half-invocation", entry->target_ptr); + ZzThreadStack *stack = ZzGetCurrentThreadStack(entry->thread_local_key); if (!stack) { #if defined(DEBUG_MODE) @@ -144,11 +146,14 @@ void function_context_half_invocation(ZzHookFunctionEntry *entry, zpointer next_ } ZzCallStack *callstack = ZzPopCallStack(stack); + /* call half_call */ if (entry->half_call) { HALFCALL half_call; half_call = entry->half_call; (*half_call)(rs, (ThreadStack *)stack, (CallStack *)callstack); } + + /* set next hop */ *(zpointer *)next_hop = (zpointer)entry->target_half_ret_addr; ZzFreeCallStack(callstack); @@ -157,6 +162,7 @@ void function_context_half_invocation(ZzHookFunctionEntry *entry, zpointer next_ // just like post_call, wow! void function_context_end_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs) { Xdebug("%p call end-invocation", entry->target_ptr); + ZzThreadStack *stack = ZzGetCurrentThreadStack(entry->thread_local_key); if (!stack) { #if defined(DEBUG_MODE) @@ -165,13 +171,15 @@ void function_context_end_invocation(ZzHookFunctionEntry *entry, zpointer next_h } ZzCallStack *callstack = ZzPopCallStack(stack); + /* call post_call */ if (entry->post_call) { POSTCALL post_call; post_call = entry->post_call; (*post_call)(rs, (ThreadStack *)stack, (CallStack *)callstack); } - *(zpointer *)next_hop = callstack->caller_ret_addr; + /* set next hop */ + *(zpointer *)next_hop = callstack->caller_ret_addr; ZzFreeCallStack(callstack); } @@ -278,6 +286,7 @@ void zz_arm64_thunker_build_enter_thunk(ZzWriter *writer) { /* save general registers and sp */ zz_arm64_writer_put_bytes(writer, (void *)ctx_save, 23 * 4); zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 8 + CTX_SAVE_STACK_OFFSET + 2 * 8); + /* trick: use the `ctx_save` left [sp]*/ zz_arm64_writer_put_str_reg_reg_offset(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 0 * 8); @@ -290,7 +299,6 @@ void zz_arm64_thunker_build_enter_thunk(ZzWriter *writer) { /* next hop*/ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 2 * 8 + 8 + CTX_SAVE_STACK_OFFSET + 0x8); - /* RegState */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X2, ZZ_ARM64_REG_SP, 2 * 8); /* caller ret address */ @@ -298,6 +306,7 @@ void zz_arm64_thunker_build_enter_thunk(ZzWriter *writer) { /* call function_context_begin_invocation */ zz_arm64_writer_put_ldr_blr_b_reg_address(writer, ZZ_ARM64_REG_X17, (zaddr)function_context_begin_invocation); + /* alignment padding + dummy PC */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 8); @@ -318,6 +327,7 @@ void zz_arm64_thunker_build_half_thunk(ZzWriter *writer) { /* save general registers and sp */ zz_arm64_writer_put_bytes(writer, (void *)ctx_save, 23 * 4); zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 8 + CTX_SAVE_STACK_OFFSET + 2 * 8); + /* trick: use the `ctx_save` left [sp]*/ zz_arm64_writer_put_str_reg_reg_offset(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 0 * 8); @@ -338,6 +348,7 @@ void zz_arm64_thunker_build_half_thunk(ZzWriter *writer) { /* call function_context_half_invocation */ zz_arm64_writer_put_ldr_blr_b_reg_address(writer, ZZ_ARM64_REG_X17, (zaddr)function_context_half_invocation); + /* alignment padding + dummy PC */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 8); @@ -454,6 +465,7 @@ void zz_arm64_thunker_build_leave_thunk(ZzWriter *writer) { /* save general registers and sp */ zz_arm64_writer_put_bytes(writer, (void *)ctx_save, 23 * 4); zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 8 + CTX_SAVE_STACK_OFFSET + 2 * 8); + /* trick: use the `ctx_save` left [sp]*/ zz_arm64_writer_put_str_reg_reg_offset(writer, ZZ_ARM64_REG_X1, ZZ_ARM64_REG_SP, 0 * 8); @@ -472,6 +484,7 @@ void zz_arm64_thunker_build_leave_thunk(ZzWriter *writer) { /* call function_context_end_invocation */ zz_arm64_writer_put_ldr_blr_b_reg_address(writer, ZZ_ARM64_REG_X17, (zaddr)function_context_end_invocation); + /* alignment padding + dummy PC */ zz_arm64_writer_put_add_reg_reg_imm(writer, ZZ_ARM64_REG_SP, ZZ_ARM64_REG_SP, 2 * 8); @@ -489,7 +502,7 @@ void zz_arm64_thunker_build_leave_thunk(ZzWriter *writer) { } ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { - zbyte temp_code_slice_data[256] = {0}; + zbyte temp_code_slice_data[512] = {0}; ZzArm64Writer *arm64_writer = NULL; ZzCodeSlice *code_slice = NULL; ZZSTATUS status = ZZ_SUCCESS; @@ -497,14 +510,17 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { 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; else return ZZ_FAILED; + /* debug log */ if (ZzIsEnableDebugMode()) { char buffer[1024] = {}; sprintf(buffer + strlen(buffer), "%s\n", "ZzThunkerBuildThunk:"); @@ -514,13 +530,18 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { } 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:"); @@ -528,14 +549,27 @@ ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { code_slice->size); ZzInfoLog("%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); + ZzInfoLog("%s", buffer); + } + return status; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-template-x86.s b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-template-x86.s new file mode 100644 index 000000000..b690233d8 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-template-x86.s @@ -0,0 +1,10 @@ +// .section __TEXT,__text,regular,pure_instructions +// .ios_version_min 11, 0 +.align 4 +.globl _ctx_save +.globl _ctx_restore +.globl _enter_thunk_template +.globl _leave_thunk_template +.globl _on_enter_trampoline_template +.globl _on_invoke_trampoline_template +.globl _on_leave_trampoline_template diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.c new file mode 100644 index 000000000..0f1fdc1ed --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.c @@ -0,0 +1,48 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "interceptor-x86.h" +#include "zzinfo.h" +#include +#include + +#define ZZ_X86_TINY_REDIRECT_SIZE 4 +#define ZZ_X86_FULL_REDIRECT_SIZE 16 + +ZzInterceptorBackend *ZzBuildInteceptorBackend(ZzAllocator *allocator) { return NULL; } + +ZzCodeSlice *zz_code_patch_x86_writer(ZzX86Writer *x86_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size) { + return NULL; +} +ZzCodeSlice *zz_code_patch_x86_relocate_writer(ZzX86Relocator *relocator, ZzX86Writer *x86_writer, + ZzAllocator *allocator, zaddr target_addr, zsize range_size) { + return NULL; +} + +ZZSTATUS ZzPrepareTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { return ZZ_FAILED; } + +ZZSTATUS ZzBuildEnterTransferTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { return ZZ_FAILED; } + +ZZSTATUS ZzBuildEnterTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { return ZZ_FAILED; } + +ZZSTATUS ZzBuildInvokeTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { return ZZ_FAILED; } + +ZZSTATUS ZzBuildHalfTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { return ZZ_FAILED; } + +ZZSTATUS ZzBuildLeaveTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { return ZZ_FAILED; } + +ZZSTATUS ZzActivateTrampoline(ZzInterceptorBackend *self, ZzHookFunctionEntry *entry) { return ZZ_FAILED; } diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.h new file mode 100644 index 000000000..39848f888 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/interceptor-x86.h @@ -0,0 +1,54 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef platforms_backend_x86_intercetor_x86 +#define platforms_backend_x86_intercetor_x86 + +// platforms +#include "platforms/arch-x86/relocator-x86.h" +#include "platforms/arch-x86/writer-x86.h" + +// hookzz +#include "allocator.h" +#include "interceptor.h" +#include "thunker.h" + +// zzdeps +#include "hookzz.h" +#include "zzdefs.h" +#include "zzdeps/common/debugbreak.h" +#include "zzdeps/zz.h" + +#define CTX_SAVE_STACK_OFFSET (8 + 30 * 8 + 8 * 16) + +typedef struct _ZzInterceptorBackend { + +} ZzInterceptorBackend; + +typedef struct _ZzX86HookFuntionEntryBackend { +} ZzX86HookFunctionEntryBackend; + +void ctx_save(); +void ctx_restore(); +void enter_thunk_template(); +void leave_thunk_template(); +void on_enter_trampoline_template(); +void on_invoke_trampoline_template(); +void on_leave_trampoline_template(); + +ZzCodeSlice *zz_code_patch_x86_writer(ZzX86Writer *x86_writer, ZzAllocator *allocator, zaddr target_addr, + zsize range_size); +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.c b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.c new file mode 100644 index 000000000..59278e206 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.c @@ -0,0 +1,115 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thunker-x86.h" +#include "zzinfo.h" +#include + + +// just like pre_call, wow! +void function_context_begin_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs, + zpointer caller_ret_addr) { + Xinfo("target %p call begin-invocation", entry->target_ptr); + + ZzThreadStack *stack = ZzGetCurrentThreadStack(entry->thread_local_key); + if (!stack) { + stack = ZzNewThreadStack(entry->thread_local_key); + } + ZzCallStack *callstack = ZzNewCallStack(); + ZzPushCallStack(stack, callstack); + + /* call pre_call */ + if (entry->pre_call) { + PRECALL pre_call; + pre_call = entry->pre_call; + (*pre_call)(rs, (ThreadStack *)stack, (CallStack *)callstack); + } + + /* set next hop */ + if (entry->replace_call) { + *(zpointer *)next_hop = entry->replace_call; + } else { + *(zpointer *)next_hop = entry->on_invoke_trampoline; + } + + if (entry->hook_type == HOOK_FUNCTION_TYPE) { + callstack->caller_ret_addr = *(zpointer *)caller_ret_addr; + *(zpointer *)caller_ret_addr = entry->on_leave_trampoline; + } +} + +// just like post_call, wow! +void function_context_half_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs, + zpointer caller_ret_addr) { + Xdebug("target %p call half-invocation", entry->target_ptr); + + ZzThreadStack *stack = ZzGetCurrentThreadStack(entry->thread_local_key); + if (!stack) { +#if defined(DEBUG_MODE) + debug_break(); +#endif + } + ZzCallStack *callstack = ZzPopCallStack(stack); + + /* call half_call */ + if (entry->half_call) { + HALFCALL half_call; + half_call = entry->half_call; + (*half_call)(rs, (ThreadStack *)stack, (CallStack *)callstack); + } + + /* set next hop */ + *(zpointer *)next_hop = (zpointer)entry->target_half_ret_addr; + + ZzFreeCallStack(callstack); +} + +// just like post_call, wow! +void function_context_end_invocation(ZzHookFunctionEntry *entry, zpointer next_hop, RegState *rs) { + Xdebug("%p call end-invocation", entry->target_ptr); + + ZzThreadStack *stack = ZzGetCurrentThreadStack(entry->thread_local_key); + if (!stack) { +#if defined(DEBUG_MODE) + debug_break(); +#endif + } + ZzCallStack *callstack = ZzPopCallStack(stack); + + /* call post_call */ + if (entry->post_call) { + POSTCALL post_call; + post_call = entry->post_call; + (*post_call)(rs, (ThreadStack *)stack, (CallStack *)callstack); + } + + /* set next hop */ + *(zpointer *)next_hop = callstack->caller_ret_addr; + ZzFreeCallStack(callstack); +} + +void zz_x86_thunker_build_enter_thunk(ZzWriter *writer) { +} + +void zz_x86_thunker_build_half_thunk(ZzWriter *writer) { +} + +void zz_x86_thunker_build_leave_thunk(ZzWriter *writer) { +} + +ZZSTATUS ZzThunkerBuildThunk(ZzInterceptorBackend *self) { + return ZZ_FAILED; +} diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.h b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.h new file mode 100644 index 000000000..554626c4a --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/src/platforms/backend-x86/thunker-x86.h @@ -0,0 +1,35 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef platforms_backend_x86_thunker_x86 +#define platforms_backend_x86_thunker_x86 + +// platforms +#include "platforms/arch-x86/relocator-x86.h" +#include "platforms/arch-x86/writer-x86.h" + +#include "interceptor-x86.h" + +// hookzz +#include "stack.h" +#include "thunker.h" + +// zzdeps +#include "hookzz.h" +#include "zzdeps/common/debugbreak.h" +#include "zzdeps/zz.h" + +#endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/src/stack.h b/VirtualApp/lib/src/main/jni/HookZz/src/stack.h index 511de7d44..0c0f6ed82 100644 --- a/VirtualApp/lib/src/main/jni/HookZz/src/stack.h +++ b/VirtualApp/lib/src/main/jni/HookZz/src/stack.h @@ -52,15 +52,10 @@ typedef struct _ZzThreadStack { } ZzThreadStack; ZzThreadStack *ZzNewThreadStack(zpointer key_ptr); - -ZzThreadStack *ZzGetCurrentThreadStack(zpointer key_ptr); - ZzCallStack *ZzNewCallStack(); - -void ZzFreeCallStack(ZzCallStack *callstack); - -ZzCallStack *ZzPopCallStack(ZzThreadStack *stack); - +ZzThreadStack *ZzGetCurrentThreadStack(zpointer key_ptr); zbool ZzPushCallStack(ZzThreadStack *stack, ZzCallStack *callstack); +ZzCallStack *ZzPopCallStack(ZzThreadStack *stack); +void ZzFreeCallStack(ZzCallStack *callstack); #endif \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/test_hook_freeaddr.c b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/test_hook_freeaddr.c new file mode 100644 index 000000000..e9a16ea1a --- /dev/null +++ b/VirtualApp/lib/src/main/jni/HookZz/tests/arm-ios/test_hook_freeaddr.c @@ -0,0 +1,70 @@ +/** + * Copyright 2017 jmpews + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hookzz.h" +#include +#include +#include + +#include +#include +#include + +void (*orig_freeaddrinfo)(struct addrinfo *ai); +void fake_freeaddrinfo(struct addrinfo *ai) { orig_freeaddrinfo(ai); } + +__attribute__((constructor)) void test_hook_freeaddrinfo() { + ZzEnableDebugMode(); + ZzHook((void *)freeaddrinfo, (void *)fake_freeaddrinfo, &orig_freeaddrinfo, NULL, NULL, FALSE); + + int sockfd; + struct addrinfo hints, *servinfo, *p; + int rv; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use AF_INET6 to force IPv6 + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; // use my IP address + + if ((rv = getaddrinfo(NULL, "3490", &hints, &servinfo)) != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); + exit(1); + } + + // loop through all the results and bind to the first we can + for (p = servinfo; p != NULL; p = p->ai_next) { + if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + perror("socket"); + continue; + } + + if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + close(sockfd); + perror("bind"); + continue; + } + + break; // if we get here, we must have connected successfully + } + + if (p == NULL) { + // looped off the end of the list with no successful bind + fprintf(stderr, "failed to bind socket\n"); + exit(2); + } + + freeaddrinfo(servinfo); // all done with this structure +} From 248438ac690cb78303a982f545e903c6c66395f6 Mon Sep 17 00:00:00 2001 From: asLody Date: Thu, 23 Nov 2017 21:51:56 +0800 Subject: [PATCH 012/334] [native] : remove armeabi abi. --- VirtualApp/lib/build.gradle | 2 +- VirtualApp/lib/src/main/jni/Application.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VirtualApp/lib/build.gradle b/VirtualApp/lib/build.gradle index 8cedbd2d3..740456fd6 100644 --- a/VirtualApp/lib/build.gradle +++ b/VirtualApp/lib/build.gradle @@ -11,7 +11,7 @@ android { versionName "1.0" externalNativeBuild { ndkBuild { - abiFilters "armeabi", "armeabi-v7a", "x86" + abiFilters "armeabi-v7a", "x86" } } } diff --git a/VirtualApp/lib/src/main/jni/Application.mk b/VirtualApp/lib/src/main/jni/Application.mk index da986993a..7ec75bdf1 100644 --- a/VirtualApp/lib/src/main/jni/Application.mk +++ b/VirtualApp/lib/src/main/jni/Application.mk @@ -1,4 +1,4 @@ -APP_ABI := armeabi armeabi-v7a x86 +APP_ABI := armeabi-v7a x86 APP_PLATFORM := android-14 APP_STL := gnustl_static APP_OPTIM := release From 5efeaa91ab85473e2d10c7f0da4358cb7f89a4f1 Mon Sep 17 00:00:00 2001 From: asLody Date: Fri, 1 Dec 2017 13:36:50 +0800 Subject: [PATCH 013/334] fix: query bug. --- VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 081091ffc..1bea70338 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -86,7 +86,8 @@ void IOUniformer::redirect(const char *orig_path, const char *new_path) { } const char *IOUniformer::query(const char *orig_path) { - return reverse_relocate_path(orig_path); + int res; + return relocate_path(orig_path, &res); } void IOUniformer::whitelist(const char *_path) { From 1ee961afb6a35a5f92949de3225968cb5580c46f Mon Sep 17 00:00:00 2001 From: david082321 Date: Sat, 2 Dec 2017 10:48:51 +0800 Subject: [PATCH 014/334] Add Chinese (Traditional) language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加繁体中文翻译 --- .../src/main/res/values-zh-rTW/strings.xml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 VirtualApp/app/src/main/res/values-zh-rTW/strings.xml diff --git a/VirtualApp/app/src/main/res/values-zh-rTW/strings.xml b/VirtualApp/app/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 000000000..84b69e6f8 --- /dev/null +++ b/VirtualApp/app/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,24 @@ + + VirtualApp + 桌面 + 新增App + 正在打開App,請稍候… + 刪除 + 建立捷徑 + 新的用戶 + 開啟 + 儲存 + 儲存成功! + 製造商 + 請稍候… + 品牌 + 機型 + 偽造裝置資訊 + Wifi狀態 + 配置裝置資訊 + 關於 + 克隆App + 外部空間 + 安裝 (%d) + 不能一次性安裝超過 9 個程式! + From 11db690f60b9950895e18f06ff7dd867b8a313a1 Mon Sep 17 00:00:00 2001 From: asLody Date: Thu, 7 Dec 2017 22:11:59 +0800 Subject: [PATCH 015/334] fix: screen compat bug. --- .../com/lody/virtual/client/VClientImpl.java | 20 +++++++++++++++++++ .../mirror/android/app/ContextImplKitkat.java | 1 + .../java/mirror/android/app/LoadedApkICS.java | 10 ++++++++++ .../mirror/android/app/LoadedApkKitkat.java | 10 ++++++++++ .../android/view/CompatibilityInfoHolder.java | 12 +++++++++++ .../android/view/DisplayAdjustments.java | 12 +++++++++++ 6 files changed, 65 insertions(+) create mode 100644 VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkICS.java create mode 100644 VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkKitkat.java create mode 100644 VirtualApp/lib/src/main/java/mirror/android/view/CompatibilityInfoHolder.java create mode 100644 VirtualApp/lib/src/main/java/mirror/android/view/DisplayAdjustments.java diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java index ff8b8349b..e06c316b7 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java @@ -12,6 +12,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; +import android.content.res.Configuration; import android.os.Binder; import android.os.Build; import android.os.ConditionVariable; @@ -20,6 +21,7 @@ import android.os.IInterface; import android.os.Looper; import android.os.Message; +import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.StrictMode; @@ -60,11 +62,17 @@ import mirror.android.app.ActivityThread; import mirror.android.app.ActivityThreadNMR1; import mirror.android.app.ContextImpl; +import mirror.android.app.ContextImplKitkat; import mirror.android.app.IActivityManager; import mirror.android.app.LoadedApk; +import mirror.android.app.LoadedApkICS; +import mirror.android.app.LoadedApkKitkat; import mirror.android.content.ContentProviderHolderOreo; +import mirror.android.content.res.CompatibilityInfo; import mirror.android.providers.Settings; import mirror.android.renderscript.RenderScriptCacheDir; +import mirror.android.view.CompatibilityInfoHolder; +import mirror.android.view.DisplayAdjustments; import mirror.android.view.HardwareRenderer; import mirror.android.view.RenderScript; import mirror.android.view.ThreadedRenderer; @@ -266,6 +274,7 @@ private void bindApplicationNoCheck(String packageName, String processName, Cond } else { codeCacheDir = context.getCacheDir(); } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { if (HardwareRenderer.setupDiskCache != null) { HardwareRenderer.setupDiskCache.call(codeCacheDir); @@ -289,6 +298,17 @@ private void bindApplicationNoCheck(String packageName, String processName, Cond mirror.android.app.ActivityThread.AppBindData.info.set(boundApp, data.info); VMRuntime.setTargetSdkVersion.call(VMRuntime.getRuntime.call(), data.appInfo.targetSdkVersion); + Configuration configuration = context.getResources().getConfiguration(); + Object compatInfo = CompatibilityInfo.ctor.newInstance(data.appInfo, configuration.screenLayout, configuration.smallestScreenWidthDp, false); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + DisplayAdjustments.setCompatibilityInfo.call(ContextImplKitkat.mDisplayAdjustments.get(context), compatInfo); + } + DisplayAdjustments.setCompatibilityInfo.call(LoadedApkKitkat.mDisplayAdjustments.get(mBoundApplication.info), compatInfo); + } else { + CompatibilityInfoHolder.set.call(LoadedApkICS.mCompatibilityInfo.get(mBoundApplication.info), compatInfo); + } + boolean conflict = SpecialComponentList.isConflictingInstrumentation(packageName); if (!conflict) { InvocationStubManager.getInstance().checkEnv(AppInstrumentation.class); diff --git a/VirtualApp/lib/src/main/java/mirror/android/app/ContextImplKitkat.java b/VirtualApp/lib/src/main/java/mirror/android/app/ContextImplKitkat.java index 8618f7160..6f92c656d 100644 --- a/VirtualApp/lib/src/main/java/mirror/android/app/ContextImplKitkat.java +++ b/VirtualApp/lib/src/main/java/mirror/android/app/ContextImplKitkat.java @@ -10,4 +10,5 @@ public class ContextImplKitkat { public static RefObject mExternalCacheDirs; public static RefObject mExternalFilesDirs; public static RefObject mOpPackageName; + public static RefObject mDisplayAdjustments; } diff --git a/VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkICS.java b/VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkICS.java new file mode 100644 index 000000000..0cc032450 --- /dev/null +++ b/VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkICS.java @@ -0,0 +1,10 @@ +package mirror.android.app; + + +import mirror.RefClass; +import mirror.RefObject; + +public class LoadedApkICS { + public static Class Class = RefClass.load(LoadedApkICS.class, "android.app.LoadedApk"); + public static RefObject mCompatibilityInfo; +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkKitkat.java b/VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkKitkat.java new file mode 100644 index 000000000..344abcd58 --- /dev/null +++ b/VirtualApp/lib/src/main/java/mirror/android/app/LoadedApkKitkat.java @@ -0,0 +1,10 @@ +package mirror.android.app; + + +import mirror.RefClass; +import mirror.RefObject; + +public class LoadedApkKitkat { + public static Class Class = RefClass.load(LoadedApkKitkat.class, "android.app.LoadedApk"); + public static RefObject mDisplayAdjustments; +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/java/mirror/android/view/CompatibilityInfoHolder.java b/VirtualApp/lib/src/main/java/mirror/android/view/CompatibilityInfoHolder.java new file mode 100644 index 000000000..c149afc29 --- /dev/null +++ b/VirtualApp/lib/src/main/java/mirror/android/view/CompatibilityInfoHolder.java @@ -0,0 +1,12 @@ +package mirror.android.view; + + +import mirror.MethodReflectParams; +import mirror.RefClass; +import mirror.RefMethod; + +public class CompatibilityInfoHolder { + public static Class Class = RefClass.load(CompatibilityInfoHolder.class, "android.view.CompatibilityInfoHolder"); + @MethodReflectParams({"android.content.res.CompatibilityInfo"}) + public static RefMethod set; +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/java/mirror/android/view/DisplayAdjustments.java b/VirtualApp/lib/src/main/java/mirror/android/view/DisplayAdjustments.java new file mode 100644 index 000000000..190010cac --- /dev/null +++ b/VirtualApp/lib/src/main/java/mirror/android/view/DisplayAdjustments.java @@ -0,0 +1,12 @@ +package mirror.android.view; + + +import mirror.MethodReflectParams; +import mirror.RefClass; +import mirror.RefMethod; + +public class DisplayAdjustments { + public static Class Class = RefClass.load(DisplayAdjustments.class, "android.view.DisplayAdjustments"); + @MethodReflectParams({"android.content.res.CompatibilityInfo"}) + public static RefMethod setCompatibilityInfo; +} \ No newline at end of file From b508fd45dad55ed5f1ca9d0a68420b8ba765ff15 Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Thu, 7 Dec 2017 22:14:01 +0800 Subject: [PATCH 016/334] Update CHINESE.md --- CHINESE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 3b8e41ede..0eea6c684 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,7 +14,9 @@ VA目前被广泛应用于双开/多开、应用市场、模拟定位、一键 申明 --- -当您需要将VirtualApp用于**商业用途**时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的App模块作为您自己的App用于牟利或上传软件市场,我们取证后将直接报警(侵犯著作权罪)。购买商业授权是对我们最大的支持和认可,我们将投入更多精力和时间来不断完善优化VirtualApp,作为购买商业授权的回报,您可以获得未开放的商业版本和1vs1的支持(技术、运营、预警)!同时我们也支持基于VirtualApp的APP订制开发,请联系:QQ:10890 洽谈。 +VirtualApp开放源代码只能用于个人技术研究和开拓思路。当您需要将VirtualApp用于商业用途时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于商业牟利、内部使用或上传软件市场,我们将直接报警(侵犯著作权罪)。 + +购买商业授权是对我们最大的支持和认可,同时也为您节省了大量的开发完善时间,保障您的产品可以高效的上线运营,让您有更多的时间去创新和盈利。作为购买商业授权的回报,您可以获得说明文档、未开放的商业版和专人1vs1对接项目(全年24小时随时微信群、QQ群、电话等1vs1负责制,保证响应时间。包括:接入对接、BUG解决、技术解答、运营建议、同行非保密运营信息分享(营收、经验、推广、弯路)、涉足行业预警)!同时我们也支持基于VirtualApp的订制开发,请联系:QQ:10890 洽谈。 请注意 ----- From 3e4bb2bf9f50fbb27bc3322f1d13919a8d931ac7 Mon Sep 17 00:00:00 2001 From: keyongyu Date: Fri, 8 Dec 2017 10:02:32 +0800 Subject: [PATCH 017/334] fix:remove last '/' --- .../lib/src/main/jni/Foundation/SandboxFs.cpp | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp b/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp index f9c3f5a5b..8ddc52c50 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp @@ -118,11 +118,19 @@ const char *relocate_path(const char *_path, int *result) { for (int i = 0; i < replace_item_count; ++i) { ReplaceItem &item = replace_items[i]; if (match_path(item.is_folder, item.orig_size, item.orig_path, path)) { - std::string redirect_path(item.new_path); - redirect_path += path + item.orig_size; *result = MATCH; - free(path); - return strdup(redirect_path.c_str()); + int len = strlen(path); + if (len < item.orig_size) { + //remove last / + std::string redirect_path(item.new_path, 0, item.new_size-1); + free(path); + return strdup(redirect_path.c_str()); + } else { + std::string redirect_path(item.new_path); + redirect_path += path + item.orig_size; + free(path); + return strdup(redirect_path.c_str()); + } } } *result = NOT_MATCH; @@ -159,10 +167,18 @@ const char *reverse_relocate_path(const char *_path) { for (int i = 0; i < replace_item_count; ++i) { ReplaceItem &item = replace_items[i]; if (match_path(item.is_folder, item.new_size, item.new_path, path)) { - std::string reverse_path(item.orig_path); - reverse_path += path + item.new_size; - free(path); - return strdup(reverse_path.c_str()); + int len = strlen(path); + if (len < item.new_size) { + //remove last / + std::string reverse_path(item.orig_path, 0, item.orig_size - 1); + free(path); + return strdup(reverse_path.c_str()); + } else { + std::string reverse_path(item.orig_path); + reverse_path += path + item.new_size; + free(path); + return strdup(reverse_path.c_str()); + } } } return _path; From eeac1c0c2f7053308f40455367b9d05ad0187047 Mon Sep 17 00:00:00 2001 From: asLody Date: Sat, 9 Dec 2017 19:28:36 +0800 Subject: [PATCH 018/334] fix: IO redirect not fully work on Android 4.4.*. --- VirtualApp/lib/src/main/jni/Android.mk | 7 +- .../src/main/jni/Foundation/IOUniformer.cpp | 14 +- .../lib/src/main/jni/Foundation/SandboxFs.cpp | 17 +- .../lib/src/main/jni/Substrate/Buffer.hpp | 38 + .../src/main/jni/Substrate/CydiaSubstrate.h | 152 +++ .../src/main/jni/Substrate/SubstrateARM.hpp | 65 ++ .../src/main/jni/Substrate/SubstrateDebug.cpp | 96 ++ .../src/main/jni/Substrate/SubstrateDebug.hpp | 33 + .../src/main/jni/Substrate/SubstrateHook.cpp | 934 ++++++++++++++++++ .../src/main/jni/Substrate/SubstrateHook.h | 19 + .../src/main/jni/Substrate/SubstrateLog.hpp | 40 + .../jni/Substrate/SubstratePosixMemory.cpp | 75 ++ .../src/main/jni/Substrate/SubstrateX86.hpp | 200 ++++ VirtualApp/lib/src/main/jni/Substrate/hde64.c | 332 +++++++ VirtualApp/lib/src/main/jni/Substrate/hde64.h | 112 +++ .../lib/src/main/jni/Substrate/table64.h | 74 ++ 16 files changed, 2186 insertions(+), 22 deletions(-) create mode 100755 VirtualApp/lib/src/main/jni/Substrate/Buffer.hpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/CydiaSubstrate.h create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstrateARM.hpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.cpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.hpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.h create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstrateLog.hpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstratePosixMemory.cpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/SubstrateX86.hpp create mode 100755 VirtualApp/lib/src/main/jni/Substrate/hde64.c create mode 100755 VirtualApp/lib/src/main/jni/Substrate/hde64.h create mode 100755 VirtualApp/lib/src/main/jni/Substrate/table64.h diff --git a/VirtualApp/lib/src/main/jni/Android.mk b/VirtualApp/lib/src/main/jni/Android.mk index 7b720825b..ee971bd28 100644 --- a/VirtualApp/lib/src/main/jni/Android.mk +++ b/VirtualApp/lib/src/main/jni/Android.mk @@ -16,10 +16,13 @@ LOCAL_SRC_FILES := Jni/VAJni.cpp \ Foundation/SymbolFinder.cpp \ Foundation/Path.cpp \ Foundation/SandboxFs.cpp \ + Substrate/hde64.c \ + Substrate/SubstrateDebug.cpp \ + Substrate/SubstrateHook.cpp \ + Substrate/SubstratePosixMemory.cpp \ LOCAL_LDLIBS := -llog -latomic -LOCAL_STATIC_LIBRARIES := hookzz fb +LOCAL_STATIC_LIBRARIES := fb include $(BUILD_SHARED_LIBRARY) -include $(MAIN_LOCAL_PATH)/HookZz/Android.mk include $(MAIN_LOCAL_PATH)/fb/Android.mk \ No newline at end of file diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 1bea70338..47f216a37 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -4,11 +4,7 @@ #include #include #include - -extern "C" { -#include -} - +#include #include "IOUniformer.h" #include "SandboxFs.h" @@ -75,7 +71,7 @@ hook_function(void *handle, const char *symbol, void *new_func, void **old_func) if (addr == NULL) { return; } - ZzHookReplace(addr, new_func, old_func); + MSHookFunction(addr, new_func, old_func); } @@ -644,19 +640,19 @@ void hook_dlopen(int api_level) { if (api_level > 23) { if (findSymbol("__dl__Z9do_dlopenPKciPK17android_dlextinfoPv", "linker", (unsigned long *) &symbol) == 0) { - ZzHookReplace(symbol, (void *) new_do_dlopen_V24, + MSHookFunction(symbol, (void *) new_do_dlopen_V24, (void **) &orig_do_dlopen_V24); } } else if (api_level >= 19) { if (findSymbol("__dl__Z9do_dlopenPKciPK17android_dlextinfo", "linker", (unsigned long *) &symbol) == 0) { - ZzHookReplace(symbol, (void *) new_do_dlopen_V19, + MSHookFunction(symbol, (void *) new_do_dlopen_V19, (void **) &orig_do_dlopen_V19); } } else { if (findSymbol("__dl_dlopen", "linker", (unsigned long *) &symbol) == 0) { - ZzHookReplace(symbol, (void *) new_dlopen, (void **) &orig_dlopen); + MSHookFunction(symbol, (void *) new_dlopen, (void **) &orig_dlopen); } } } diff --git a/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp b/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp index 8ddc52c50..9f352d20c 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/SandboxFs.cpp @@ -80,7 +80,7 @@ int get_replace_item_count() { return replace_item_count; } -inline bool match_path(bool is_folder, size_t size, char *item_path, char *path) { +inline bool match_path(bool is_folder, size_t size, const char *item_path, const char *path) { if (is_folder) { if (strlen(path) < size) { // ignore the last '/' @@ -91,18 +91,16 @@ inline bool match_path(bool is_folder, size_t size, char *item_path, char *path) } -const char *relocate_path(const char *_path, int *result) { - if (_path == NULL) { +const char *relocate_path(const char *path, int *result) { + if (path == NULL) { *result = NOT_MATCH; return NULL; } - char *path = canonicalize_filename(_path); for (int i = 0; i < keep_item_count; ++i) { PathItem &item = keep_items[i]; if (strcmp(item.path, path) == 0) { *result = KEEP; - free(path); - return _path; + return path; } } for (int i = 0; i < forbidden_item_count; ++i) { @@ -111,7 +109,6 @@ const char *relocate_path(const char *_path, int *result) { *result = FORBID; // Permission denied errno = 13; - free(path); return NULL; } } @@ -122,19 +119,17 @@ const char *relocate_path(const char *_path, int *result) { int len = strlen(path); if (len < item.orig_size) { //remove last / - std::string redirect_path(item.new_path, 0, item.new_size-1); - free(path); + std::string redirect_path(item.new_path, 0, item.new_size - 1); return strdup(redirect_path.c_str()); } else { std::string redirect_path(item.new_path); redirect_path += path + item.orig_size; - free(path); return strdup(redirect_path.c_str()); } } } *result = NOT_MATCH; - return _path; + return path; } diff --git a/VirtualApp/lib/src/main/jni/Substrate/Buffer.hpp b/VirtualApp/lib/src/main/jni/Substrate/Buffer.hpp new file mode 100755 index 000000000..34d9df32e --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/Buffer.hpp @@ -0,0 +1,38 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_BUFFER_HPP +#define SUBSTRATE_BUFFER_HPP + +#include + +template +_disused static _finline void MSWrite(uint8_t *&buffer, Type_ value) { + *reinterpret_cast(buffer) = value; + buffer += sizeof(Type_); +} + +_disused static _finline void MSWrite(uint8_t *&buffer, uint8_t *data, size_t size) { + memcpy(buffer, data, size); + buffer += size; +} + +#endif//SUBSTRATE_BUFFER_HPP diff --git a/VirtualApp/lib/src/main/jni/Substrate/CydiaSubstrate.h b/VirtualApp/lib/src/main/jni/Substrate/CydiaSubstrate.h new file mode 100755 index 000000000..bb806aa9f --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/CydiaSubstrate.h @@ -0,0 +1,152 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_H_ +#define SUBSTRATE_H_ + +#ifdef __APPLE__ +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif + +#include +#include +#endif + +#include +#include + +#define _finline \ + inline __attribute__((__always_inline__)) +#define _disused \ + __attribute__((__unused__)) + +#define _extern \ + extern "C" __attribute__((__visibility__("default"))) + +#ifdef __cplusplus +#define _default(value) = value +#else +#define _default(value) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +bool MSHookProcess(pid_t pid, const char *library); + +typedef const void *MSImageRef; + +MSImageRef MSGetImageByName(const char *file); +void *MSFindSymbol(MSImageRef image, const char *name); + +void MSHookFunction(void *symbol, void *replace, void **result); + +#ifdef __APPLE__ +#ifdef __arm__ +__attribute__((__deprecated__)) +IMP MSHookMessage(Class _class, SEL sel, IMP imp, const char *prefix _default(NULL)); +#endif +void MSHookMessageEx(Class _class, SEL sel, IMP imp, IMP *result); +#endif + +#ifdef SubstrateInternal +typedef void *SubstrateAllocatorRef; +typedef struct __SubstrateProcess *SubstrateProcessRef; +typedef struct __SubstrateMemory *SubstrateMemoryRef; + +SubstrateProcessRef SubstrateProcessCreate(SubstrateAllocatorRef allocator, pid_t pid); +void SubstrateProcessRelease(SubstrateProcessRef process); + +SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size); +void SubstrateMemoryRelease(SubstrateMemoryRef memory); +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +#ifdef SubstrateInternal +struct SubstrateHookMemory { + SubstrateMemoryRef handle_; + + SubstrateHookMemory(SubstrateProcessRef process, void *data, size_t size) : + handle_(SubstrateMemoryCreate(NULL, NULL, data, size)) + { + } + + ~SubstrateHookMemory() { + if (handle_ != NULL) + SubstrateMemoryRelease(handle_); + } +}; +#endif + + +template +static inline void MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result) { + MSHookFunction( + reinterpret_cast(symbol), + reinterpret_cast(replace), + reinterpret_cast(result) + ); +} + +template +static inline void MSHookFunction(Type_ *symbol, Type_ *replace) { + return MSHookFunction(symbol, replace, reinterpret_cast(NULL)); +} + +template +static inline void MSHookSymbol(Type_ *&value, const char *name, MSImageRef image = NULL) { + value = reinterpret_cast(MSFindSymbol(image, name)); +} + +template +static inline void MSHookFunction(const char *name, Type_ *replace, Type_ **result = NULL) { + Type_ *symbol; + MSHookSymbol(symbol, name); + return MSHookFunction(symbol, replace, result); +} + +#endif + +#define MSHook(type, name, args...) \ + _disused static type (*_ ## name)(args); \ + static type $ ## name(args) + +#ifdef __cplusplus +#define MSHake(name) \ + &$ ## name, &_ ## name +#else +#define MSHake(name) \ + &$ ## name, (void **) &_ ## name +#endif + + +#endif//SUBSTRATE_H_ diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateARM.hpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateARM.hpp new file mode 100755 index 000000000..7dd313900 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateARM.hpp @@ -0,0 +1,65 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_ARM_HPP +#define SUBSTRATE_ARM_HPP + +enum A$r { + A$r0, A$r1, A$r2, A$r3, + A$r4, A$r5, A$r6, A$r7, + A$r8, A$r9, A$r10, A$r11, + A$r12, A$r13, A$r14, A$r15, + A$sp = A$r13, + A$lr = A$r14, + A$pc = A$r15 +}; + +enum A$c { + A$eq, A$ne, A$cs, A$cc, + A$mi, A$pl, A$vs, A$vc, + A$hi, A$ls, A$ge, A$lt, + A$gt, A$le, A$al, + A$hs = A$cs, + A$lo = A$cc +}; + +#define A$mrs_rm_cpsr(rd) /* mrs rd, cpsr */ \ + (0xe10f0000 | ((rd) << 12)) +#define A$msr_cpsr_f_rm(rm) /* msr cpsr_f, rm */ \ + (0xe128f000 | (rm)) +#define A$ldr_rd_$rn_im$(rd, rn, im) /* ldr rd, [rn, #im] */ \ + (0xe5100000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) +#define A$str_rd_$rn_im$(rd, rn, im) /* sr rd, [rn, #im] */ \ + (0xe5000000 | ((im) < 0 ? 0 : 1 << 23) | ((rn) << 16) | ((rd) << 12) | abs(im)) +#define A$sub_rd_rn_$im(rd, rn, im) /* sub, rd, rn, #im */ \ + (0xe2400000 | ((rn) << 16) | ((rd) << 12) | (im & 0xff)) +#define A$blx_rm(rm) /* blx rm */ \ + (0xe12fff30 | (rm)) +#define A$mov_rd_rm(rd, rm) /* mov rd, rm */ \ + (0xe1a00000 | ((rd) << 12) | (rm)) +#define A$ldmia_sp$_$rs$(rs) /* ldmia sp!, {rs} */ \ + (0xe8b00000 | (A$sp << 16) | (rs)) +#define A$stmdb_sp$_$rs$(rs) /* stmdb sp!, {rs} */ \ + (0xe9200000 | (A$sp << 16) | (rs)) +#define A$stmia_sp$_$r0$ 0xe8ad0001 /* stmia sp!, {r0} */ +#define A$bx_r0 0xe12fff10 /* bx r0 */ + +#endif//SUBSTRATE_ARM_HPP diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.cpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.cpp new file mode 100755 index 000000000..2df6ef487 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.cpp @@ -0,0 +1,96 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#include "SubstrateHook.h" +#include "SubstrateDebug.hpp" + +#include +#include +#include + +_extern bool MSDebug; +bool MSDebug = false; + +static char _MSHexChar(uint8_t value) { + return value < 0x20 || value >= 0x80 ? '.' : value; +} + +#define HexWidth_ 16 +#define HexDepth_ 4 + +void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark) { + const uint8_t *data((const uint8_t *) vdata); + + size_t i(0), j; + + char d[256]; + size_t b(0); + d[0] = '\0'; + + while (i != size) { + if (i % HexWidth_ == 0) { + if (mark != NULL) + b += sprintf(d + b, "\n[%s] ", mark); + b += sprintf(d + b, "0x%.3zx:", i); + } + + b += sprintf(d + b, " "); + + for (size_t q(0); q != stride; ++q) + b += sprintf(d + b, "%.2x", data[i + stride - q - 1]); + + i += stride; + + for (size_t q(1); q != stride; ++q) + b += sprintf(d + b, " "); + + if (i % HexDepth_ == 0) + b += sprintf(d + b, " "); + + if (i % HexWidth_ == 0) { + b += sprintf(d + b, " "); + for (j = i - HexWidth_; j != i; ++j) + b += sprintf(d + b, "%c", _MSHexChar(data[j])); + + lprintf("%s", d); + b = 0; + d[0] = '\0'; + } + } + + if (i % HexWidth_ != 0) { + for (j = i % HexWidth_; j != HexWidth_; ++j) + b += sprintf(d + b, " "); + for (j = 0; j != (HexWidth_ - i % HexWidth_ + HexDepth_ - 1) / HexDepth_; ++j) + b += sprintf(d + b, " "); + b += sprintf(d + b, " "); + for (j = i / HexWidth_ * HexWidth_; j != i; ++j) + b += sprintf(d + b, "%c", _MSHexChar(data[j])); + + lprintf("%s", d); + b = 0; + d[0] = '\0'; + } +} + +void MSLogHex(const void *vdata, size_t size, const char *mark) { + return MSLogHexEx(vdata, size, 1, mark); +} diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.hpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.hpp new file mode 100755 index 000000000..9c554c851 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateDebug.hpp @@ -0,0 +1,33 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_DEBUG_HPP +#define SUBSTRATE_DEBUG_HPP + +#include "SubstrateLog.hpp" +#define lprintf(format, ...) \ + MSLog(MSLogLevelNotice, format, ## __VA_ARGS__) + +extern "C" bool MSDebug; +void MSLogHexEx(const void *vdata, size_t size, size_t stride, const char *mark = 0); +void MSLogHex(const void *vdata, size_t size, const char *mark = 0); + +#endif//SUBSTRATE_DEBUG_HPP diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp new file mode 100755 index 000000000..34f2a26dd --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.cpp @@ -0,0 +1,934 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#define SubstrateInternal +#include "CydiaSubstrate.h" + +#include + +#define _trace() do { \ + MSLog(MSLogLevelNotice, "_trace(%u)", __LINE__); \ +} while (false) + +#if defined(__i386__) || defined(__x86_64__) +#include "hde64.h" +#endif + +#include "SubstrateDebug.hpp" + +#include +#include +#include + +#ifdef __arm__ +/* WebCore (ARM) PC-Relative: +X 1 ldr r*,[pc,r*] != + 2 fldd d*,[pc,#*] +X 5 str r*,[pc,r*] != + 8 flds s*,[pc,#*] + 400 ldr r*,[pc,r*] == + 515 add r*, pc,r* == +X 4790 ldr r*,[pc,#*] */ + +// x=0; while IFS= read -r line; do if [[ ${#line} -ne 0 && $line == +([^\;]): ]]; then x=2; elif [[ $line == ' +'* && $x -ne 0 ]]; then ((--x)); echo "$x${line}"; fi; done WebCore.pc +// grep pc WebCore.pc | cut -c 40- | sed -Ee 's/^ldr *(ip|r[0-9]*),\[pc,\#0x[0-9a-f]*\].*/ ldr r*,[pc,#*]/;s/^add *r[0-9]*,pc,r[0-9]*.*/ add r*, pc,r*/;s/^(st|ld)r *r([0-9]*),\[pc,r([0-9]*)\].*/ \1r r\2,[pc,r\3]/;s/^fld(s|d) *(s|d)[0-9]*,\[pc,#0x[0-9a-f]*].*/fld\1 \2*,[pc,#*]/' | sort | uniq -c | sort -n + +#include "SubstrateARM.hpp" + +#define T$Label(l, r) \ + (((r) - (l)) * 2 - 4 + ((l) % 2 == 0 ? 0 : 2)) + +#define T$pop_$r0$ 0xbc01 // pop {r0} +#define T$b(im) /* b im */ \ + (0xde00 | (im & 0xff)) +#define T$blx(rm) /* blx rm */ \ + (0x4780 | (rm << 3)) +#define T$bx(rm) /* bx rm */ \ + (0x4700 | (rm << 3)) +#define T$nop /* nop */ \ + (0x46c0) + +#define T$add_rd_rm(rd, rm) /* add rd, rm */ \ + (0x4400 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) +#define T$push_r(r) /* push r... */ \ + (0xb400 | (((r) & (1 << A$lr)) >> A$lr << 8) | ((r) & 0xff)) +#define T$pop_r(r) /* pop r... */ \ + (0xbc00 | (((r) & (1 << A$pc)) >> A$pc << 8) | ((r) & 0xff)) +#define T$mov_rd_rm(rd, rm) /* mov rd, rm */ \ + (0x4600 | (((rd) & 0x8) >> 3 << 7) | (((rm) & 0x8) >> 3 << 6) | (((rm) & 0x7) << 3) | ((rd) & 0x7)) +#define T$ldr_rd_$rn_im_4$(rd, rn, im) /* ldr rd, [rn, #im * 4] */ \ + (0x6800 | (((im) & 0x1f) << 6) | ((rn) << 3) | (rd)) +#define T$ldr_rd_$pc_im_4$(rd, im) /* ldr rd, [PC, #im * 4] */ \ + (0x4800 | ((rd) << 8) | ((im) & 0xff)) +#define T$cmp_rn_$im(rn, im) /* cmp rn, #im */ \ + (0x2000 | ((rn) << 8) | ((im) & 0xff)) +#define T$it$_cd(cd, ms) /* it, cd */ \ + (0xbf00 | ((cd) << 4) | (ms)) +#define T$cbz$_rn_$im(op,rn,im) /* cbz rn, #im */ \ + (0xb100 | ((op) << 11) | (((im) & 0x40) >> 6 << 9) | (((im) & 0x3e) >> 1 << 3) | (rn)) +#define T$b$_$im(cond,im) /* b #im */ \ + (cond == A$al ? 0xe000 | (((im) >> 1) & 0x7ff) : 0xd000 | ((cond) << 8) | (((im) >> 1) & 0xff)) + +#define T1$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ + (0xf850 | ((im < 0 ? 0 : 1) << 7) | (rn)) +#define T2$ldr_rt_$rn_im$(rt, rn, im) /* ldr rt, [rn, #im] */ \ + (((rt) << 12) | abs(im)) + +#define T1$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ + (0xf3ef) +#define T2$mrs_rd_apsr(rd) /* mrs rd, apsr */ \ + (0x8000 | ((rd) << 8)) + +#define T1$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ + (0xf380 | (rn)) +#define T2$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ + (0x8c00) +#define T$msr_apsr_nzcvqg_rn(rn) /* msr apsr, rn */ \ + (T2$msr_apsr_nzcvqg_rn(rn) << 16 | T1$msr_apsr_nzcvqg_rn(rn)) + +static inline bool A$pcrel$r(uint32_t ic) { + return (ic & 0x0c000000) == 0x04000000 && (ic & 0xf0000000) != 0xf0000000 && (ic & 0x000f0000) == 0x000f0000; +} + +static inline bool T$32bit$i(uint16_t ic) { + return ((ic & 0xe000) == 0xe000 && (ic & 0x1800) != 0x0000); +} + +static inline bool T$pcrel$cbz(uint16_t ic) { + return (ic & 0xf500) == 0xb100; +} + +static inline bool T$pcrel$b(uint16_t ic) { + return (ic & 0xf000) == 0xd000 && (ic & 0x0e00) != 0x0e00; +} + +static inline bool T2$pcrel$b(uint16_t *ic) { + return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0x9000 || (ic[1] & 0xd000) == 0x8000 && (ic[0] & 0x0380) != 0x0380); +} + +static inline bool T$pcrel$bl(uint16_t *ic) { + return (ic[0] & 0xf800) == 0xf000 && ((ic[1] & 0xd000) == 0xd000 || (ic[1] & 0xd001) == 0xc000); +} + +static inline bool T$pcrel$ldr(uint16_t ic) { + return (ic & 0xf800) == 0x4800; +} + +static inline bool T$pcrel$add(uint16_t ic) { + return (ic & 0xff78) == 0x4478; +} + +static inline bool T$pcrel$ldrw(uint16_t ic) { + return (ic & 0xff7f) == 0xf85f; +} + +static size_t MSGetInstructionWidthThumb(void *start) { + uint16_t *thumb(reinterpret_cast(start)); + return T$32bit$i(thumb[0]) ? 4 : 2; +} + +static size_t MSGetInstructionWidthARM(void *start) { + return 4; +} + +extern "C" size_t MSGetInstructionWidth(void *start) { + if ((reinterpret_cast(start) & 0x1) == 0) + return MSGetInstructionWidthARM(start); + else + return MSGetInstructionWidthThumb(reinterpret_cast(reinterpret_cast(start) & ~0x1)); +} + +static size_t SubstrateHookFunctionThumb(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (symbol == NULL) + return 0; +printf("SubstrateHookFunctionThumb\n"); + uint16_t *area(reinterpret_cast(symbol)); + + unsigned align((reinterpret_cast(area) & 0x2) == 0 ? 0 : 1); + uint16_t *thumb(area + align); + + uint32_t *arm(reinterpret_cast(thumb + 2)); + uint16_t *trail(reinterpret_cast(arm + 2)); + + if ( + (align == 0 || area[0] == T$nop) && + thumb[0] == T$bx(A$pc) && + thumb[1] == T$nop && + arm[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8) + ) { + if (result != NULL) + *result = reinterpret_cast(arm[1]); + + SubstrateHookMemory code(process, arm + 1, sizeof(uint32_t) * 1); + + arm[1] = reinterpret_cast(replace); + + return sizeof(arm[0]); + } + + size_t required((trail - area) * sizeof(uint16_t)); + + size_t used(0); + while (used < required) + used += MSGetInstructionWidthThumb(reinterpret_cast(area) + used); + used = (used + sizeof(uint16_t) - 1) / sizeof(uint16_t) * sizeof(uint16_t); + + size_t blank((used - required) / sizeof(uint16_t)); + + uint16_t backup[used / sizeof(uint16_t)]; + memcpy(backup, area, used); + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint16_t), 2, name); + } + + if (result != NULL) { + + size_t length(used); + for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) + if (T$pcrel$ldr(backup[offset])) + length += 3 * sizeof(uint16_t); + else if (T$pcrel$b(backup[offset])) + length += 6 * sizeof(uint16_t); + else if (T2$pcrel$b(backup + offset)) { + length += 5 * sizeof(uint16_t); + ++offset; + } else if (T$pcrel$bl(backup + offset)) { + length += 5 * sizeof(uint16_t); + ++offset; + } else if (T$pcrel$cbz(backup[offset])) { + length += 16 * sizeof(uint16_t); + } else if (T$pcrel$ldrw(backup[offset])) { + length += 4 * sizeof(uint16_t); + ++offset; + } else if (T$pcrel$add(backup[offset])) + length += 6 * sizeof(uint16_t); + else if (T$32bit$i(backup[offset])) + ++offset; + + unsigned pad((length & 0x2) == 0 ? 0 : 1); + length += (pad + 2) * sizeof(uint16_t) + 2 * sizeof(uint32_t); + + uint16_t *buffer(reinterpret_cast(mmap( + NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 + ))); + + if (buffer == MAP_FAILED) { + MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); + *result = NULL; + return 0; + } + + if (false) fail: { + munmap(buffer, length); + *result = NULL; + return 0; + } + + size_t start(pad), end(length / sizeof(uint16_t)); + uint32_t *trailer(reinterpret_cast(buffer + end)); + for (unsigned offset(0); offset != used / sizeof(uint16_t); ++offset) { + if (T$pcrel$ldr(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t immediate : 8; + uint16_t rd : 3; + uint16_t : 5; + }; + } bits = {backup[offset+0]}; + + buffer[start+0] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+0, end-2) / 4); + buffer[start+1] = T$ldr_rd_$rn_im_4$(bits.rd, bits.rd, 0); + + // XXX: this code "works", but is "wrong": the mechanism is more complex than this + *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + bits.immediate * 4; + + start += 2; + end -= 2; + } else if (T$pcrel$b(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t imm8 : 8; + uint16_t cond : 4; + uint16_t /*1101*/ : 4; + }; + } bits = {backup[offset+0]}; + + intptr_t jump(bits.imm8 << 1); + jump |= 1; + jump <<= 23; + jump >>= 23; + + buffer[start+0] = T$b$_$im(bits.cond, (end-6 - (start+0)) * 2 - 4); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + *--trailer = T$nop << 16 | T$bx(A$pc); + + start += 1; + end -= 6; + } else if (T2$pcrel$b(backup + offset)) { + union { + uint16_t value; + + struct { + uint16_t imm6 : 6; + uint16_t cond : 4; + uint16_t s : 1; + uint16_t : 5; + }; + } bits = {backup[offset+0]}; + + union { + uint16_t value; + + struct { + uint16_t imm11 : 11; + uint16_t j2 : 1; + uint16_t a : 1; + uint16_t j1 : 1; + uint16_t : 2; + }; + } exts = {backup[offset+1]}; + + intptr_t jump(1); + jump |= exts.imm11 << 1; + jump |= bits.imm6 << 12; + + if (exts.a) { + jump |= bits.s << 24; + jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; + jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; + jump |= bits.cond << 18; + jump <<= 7; + jump >>= 7; + } else { + jump |= bits.s << 20; + jump |= exts.j2 << 19; + jump |= exts.j1 << 18; + jump <<= 11; + jump >>= 11; + } + + buffer[start+0] = T$b$_$im(exts.a ? A$al : bits.cond, (end-6 - (start+0)) * 2 - 4); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + *--trailer = T$nop << 16 | T$bx(A$pc); + + ++offset; + start += 1; + end -= 6; + } else if (T$pcrel$bl(backup + offset)) { + union { + uint16_t value; + + struct { + uint16_t immediate : 10; + uint16_t s : 1; + uint16_t : 5; + }; + } bits = {backup[offset+0]}; + + union { + uint16_t value; + + struct { + uint16_t immediate : 11; + uint16_t j2 : 1; + uint16_t x : 1; + uint16_t j1 : 1; + uint16_t : 2; + }; + } exts = {backup[offset+1]}; + + int32_t jump(0); + jump |= bits.s << 24; + jump |= (~(bits.s ^ exts.j1) & 0x1) << 23; + jump |= (~(bits.s ^ exts.j2) & 0x1) << 22; + jump |= bits.immediate << 12; + jump |= exts.immediate << 1; + jump |= exts.x; + jump <<= 7; + jump >>= 7; + + buffer[start+0] = T$push_r(1 << A$r7); + buffer[start+1] = T$ldr_rd_$pc_im_4$(A$r7, ((end-2 - (start+1)) * 2 - 4 + 2) / 4); + buffer[start+2] = T$mov_rd_rm(A$lr, A$r7); + buffer[start+3] = T$pop_r(1 << A$r7); + buffer[start+4] = T$blx(A$lr); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + + ++offset; + start += 5; + end -= 2; + } else if (T$pcrel$cbz(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t rn : 3; + uint16_t immediate : 5; + uint16_t : 1; + uint16_t i : 1; + uint16_t : 1; + uint16_t op : 1; + uint16_t : 4; + }; + } bits = {backup[offset+0]}; + + intptr_t jump(1); + jump |= bits.i << 6; + jump |= bits.immediate << 1; + + //jump <<= 24; + //jump >>= 24; + + unsigned rn(bits.rn); + unsigned rt(rn == A$r7 ? A$r6 : A$r7); + + buffer[start+0] = T$push_r(1 << rt); + buffer[start+1] = T1$mrs_rd_apsr(rt); + buffer[start+2] = T2$mrs_rd_apsr(rt); + buffer[start+3] = T$cbz$_rn_$im(bits.op, rn, (end-10 - (start+3)) * 2 - 4); + buffer[start+4] = T1$msr_apsr_nzcvqg_rn(rt); + buffer[start+5] = T2$msr_apsr_nzcvqg_rn(rt); + buffer[start+6] = T$pop_r(1 << rt); + + *--trailer = reinterpret_cast(area + offset) + 4 + jump; + *--trailer = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + *--trailer = T$nop << 16 | T$bx(A$pc); + *--trailer = T$nop << 16 | T$pop_r(1 << rt); + *--trailer = T$msr_apsr_nzcvqg_rn(rt); + +#if 0 + if ((start & 0x1) == 0) + buffer[start++] = T$nop; + buffer[start++] = T$bx(A$pc); + buffer[start++] = T$nop; + + uint32_t *arm(reinterpret_cast(buffer + start)); + arm[0] = A$add(A$lr, A$pc, 1); + arm[1] = A$ldr_rd_$rn_im$(A$pc, A$pc, (trailer - arm) * sizeof(uint32_t) - 8); +#endif + + start += 7; + end -= 10; + } else if (T$pcrel$ldrw(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t : 7; + uint16_t u : 1; + uint16_t : 8; + }; + } bits = {backup[offset+0]}; + + union { + uint16_t value; + + struct { + uint16_t immediate : 12; + uint16_t rt : 4; + }; + } exts = {backup[offset+1]}; + + buffer[start+0] = T1$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); + buffer[start+1] = T2$ldr_rt_$rn_im$(exts.rt, A$pc, T$Label(start+0, end-2)); + + buffer[start+2] = T1$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); + buffer[start+3] = T2$ldr_rt_$rn_im$(exts.rt, exts.rt, 0); + + // XXX: this code "works", but is "wrong": the mechanism is more complex than this + *--trailer = ((reinterpret_cast(area + offset) + 4) & ~0x2) + (bits.u == 0 ? -exts.immediate : exts.immediate); + + ++offset; + start += 4; + end -= 2; + } else if (T$pcrel$add(backup[offset])) { + union { + uint16_t value; + + struct { + uint16_t rd : 3; + uint16_t rm : 3; + uint16_t h2 : 1; + uint16_t h1 : 1; + uint16_t : 8; + }; + } bits = {backup[offset+0]}; + + if (bits.h1) { + MSLog(MSLogLevelError, "MS:Error:pcrel(%u):add (rd > r7)", offset); + goto fail; + } + + unsigned rt(bits.rd == A$r7 ? A$r6 : A$r7); + + buffer[start+0] = T$push_r(1 << rt); + buffer[start+1] = T$mov_rd_rm(rt, (bits.h1 << 3) | bits.rd); + buffer[start+2] = T$ldr_rd_$pc_im_4$(bits.rd, T$Label(start+2, end-2) / 4); + buffer[start+3] = T$add_rd_rm((bits.h1 << 3) | bits.rd, rt); + buffer[start+4] = T$pop_r(1 << rt); + *--trailer = reinterpret_cast(area + offset) + 4; + + start += 5; + end -= 2; + } else if (T$32bit$i(backup[offset])) { + buffer[start++] = backup[offset]; + buffer[start++] = backup[++offset]; + } else { + buffer[start++] = backup[offset]; + } + } + + buffer[start++] = T$bx(A$pc); + buffer[start++] = T$nop; + + uint32_t *transfer = reinterpret_cast(buffer + start); + transfer[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + transfer[1] = reinterpret_cast(area + used / sizeof(uint16_t)) + 1; + + if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); + return 0; + } + + *result = reinterpret_cast(buffer + pad) + 1; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", *result); + MSLogHexEx(buffer, length, 2, name); + } + + } + + { + SubstrateHookMemory code(process, area, used); + + if (align != 0) + area[0] = T$nop; + + thumb[0] = T$bx(A$pc); + thumb[1] = T$nop; + + arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + arm[1] = reinterpret_cast(replace); + + for (unsigned offset(0); offset != blank; ++offset) + trail[offset] = T$nop; + } + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint16_t), 2, name); + } + + return used; +} + +static size_t SubstrateHookFunctionARM(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (symbol == NULL) + return 0; +printf("SubstrateHookFunctionARM\n"); + uint32_t *area(reinterpret_cast(symbol)); + uint32_t *arm(area); + + const size_t used(8); + + uint32_t backup[used / sizeof(uint32_t)] = {arm[0], arm[1]}; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint32_t), 4, name); + } + + if (result != NULL) { + + if (backup[0] == A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8)) { + *result = reinterpret_cast(backup[1]); + + return sizeof(backup[0]); + } + + size_t length(used); + for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) + if (A$pcrel$r(backup[offset])) { + if ((backup[offset] & 0x02000000) == 0 || (backup[offset] & 0x0000f000 >> 12) != (backup[offset] & 0x0000000f)) + length += 2 * sizeof(uint32_t); + else + length += 4 * sizeof(uint32_t); + } + + length += 2 * sizeof(uint32_t); + + uint32_t *buffer(reinterpret_cast(mmap( + NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 + ))); + + if (buffer == MAP_FAILED) { + MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); + *result = NULL; + return 0; + } + + if (false) fail: { + munmap(buffer, length); + *result = NULL; + return 0; + } + + size_t start(0), end(length / sizeof(uint32_t)); + uint32_t *trailer(reinterpret_cast(buffer + end)); + for (unsigned offset(0); offset != used / sizeof(uint32_t); ++offset) + if (A$pcrel$r(backup[offset])) { + union { + uint32_t value; + + struct { + uint32_t rm : 4; + uint32_t : 1; + uint32_t shift : 2; + uint32_t shiftamount : 5; + uint32_t rd : 4; + uint32_t rn : 4; + uint32_t l : 1; + uint32_t w : 1; + uint32_t b : 1; + uint32_t u : 1; + uint32_t p : 1; + uint32_t mode : 1; + uint32_t type : 2; + uint32_t cond : 4; + }; + } bits = {backup[offset+0]}, copy(bits); + + bool guard; + if (bits.mode == 0 || bits.rd != bits.rm) { + copy.rn = bits.rd; + guard = false; + } else { + copy.rn = bits.rm != A$r0 ? A$r0 : A$r1; + guard = true; + } + + if (guard) + buffer[start++] = A$stmdb_sp$_$rs$((1 << copy.rn)); + + buffer[start+0] = A$ldr_rd_$rn_im$(copy.rn, A$pc, (end-1 - (start+0)) * 4 - 8); + buffer[start+1] = copy.value; + + start += 2; + + if (guard) + buffer[start++] = A$ldmia_sp$_$rs$((1 << copy.rn)); + + *--trailer = reinterpret_cast(area + offset) + 8; + end -= 1; + } else + buffer[start++] = backup[offset]; + + buffer[start+0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + buffer[start+1] = reinterpret_cast(area + used / sizeof(uint32_t)); + + if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); + goto fail; + } + + *result = buffer; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", *result); + MSLogHexEx(buffer, length, 4, name); + } + + } + + { + SubstrateHookMemory code(process, symbol, used); + + arm[0] = A$ldr_rd_$rn_im$(A$pc, A$pc, 4 - 8); + arm[1] = reinterpret_cast(replace); + } + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHexEx(area, used + sizeof(uint32_t), 4, name); + } + + return used; +} + +static size_t SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (MSDebug) + MSLog(MSLogLevelNotice, "SubstrateHookFunction(%p, %p, %p, %p)\n", process, symbol, replace, result); + if ((reinterpret_cast(symbol) & 0x1) == 0) + return SubstrateHookFunctionARM(process, symbol, replace, result); + else + return SubstrateHookFunctionThumb(process, reinterpret_cast(reinterpret_cast(symbol) & ~0x1), replace, result); +} +#endif + +#if defined(__i386__) || defined(__x86_64__) + +#include "SubstrateX86.hpp" + +static size_t MSGetInstructionWidthIntel(void *start) { + hde64s decode; + return hde64_disasm(start, &decode); +} + +static void SubstrateHookFunction(SubstrateProcessRef process, void *symbol, void *replace, void **result) { + if (MSDebug) + MSLog(MSLogLevelNotice, "MSHookFunction(%p, %p, %p)\n", symbol, replace, result); + if (symbol == NULL) + return; + + uintptr_t source(reinterpret_cast(symbol)); + uintptr_t target(reinterpret_cast(replace)); + + uint8_t *area(reinterpret_cast(symbol)); + + size_t required(MSSizeOfJump(target, source)); + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHex(area, 32, name); + } + + size_t used(0); + while (used < required) { + size_t width(MSGetInstructionWidthIntel(area + used)); + if (width == 0) { + MSLog(MSLogLevelError, "MS:Error:MSGetInstructionWidthIntel(%p) == 0", area + used); + return; + } + + used += width; + } + + size_t blank(used - required); + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHex(area, used + sizeof(uint16_t), name); + } + + uint8_t backup[used]; + memcpy(backup, area, used); + + if (result != NULL) { + + if (backup[0] == 0xe9) { + *result = reinterpret_cast(source + 5 + *reinterpret_cast(backup + 1)); + return; + } + + if (!ia32 && backup[0] == 0xff && backup[1] == 0x25) { + *result = *reinterpret_cast(source + 6 + *reinterpret_cast(backup + 2)); + return; + } + + size_t length(used + MSSizeOfJump(source + used)); + + for (size_t offset(0), width; offset != used; offset += width) { + hde64s decode; + hde64_disasm(backup + offset, &decode); + width = decode.len; + //_assert(width != 0 && offset + width <= used); + +#ifdef __LP64__ + if ((decode.modrm & 0xc7) == 0x05) { + if (decode.opcode == 0x8b) { + void *destiny(area + offset + width + int32_t(decode.disp.disp32)); + uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); + length -= decode.len; + length += MSSizeOfPushPointer(destiny); + length += MSSizeOfPop(reg); + length += MSSizeOfMove64(); + } else { + MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); + continue; + } + } else +#endif + + if (backup[offset] == 0xe8) { + int32_t relative(*reinterpret_cast(backup + offset + 1)); + void *destiny(area + offset + decode.len + relative); + + if (relative == 0) { + length -= decode.len; + length += MSSizeOfPushPointer(destiny); + } else { + length += MSSizeOfSkip(); + length += MSSizeOfJump(destiny); + } + } else if (backup[offset] == 0xeb) { + length -= decode.len; + length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + } else if (backup[offset] == 0xe9) { + length -= decode.len; + length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + } else if ( + backup[offset] == 0xe3 || + (backup[offset] & 0xf0) == 0x70 + // XXX: opcode2 & 0xf0 is 0x80? + ) { + length += decode.len; + length += MSSizeOfJump(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + } + } + + uint8_t *buffer(reinterpret_cast(mmap( + NULL, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 + ))); + + if (buffer == MAP_FAILED) { + MSLog(MSLogLevelError, "MS:Error:mmap() = %d", errno); + *result = NULL; + return; + } + + if (false) fail: { + munmap(buffer, length); + *result = NULL; + return; + } + + { + uint8_t *current(buffer); + + for (size_t offset(0), width; offset != used; offset += width) { + hde64s decode; + hde64_disasm(backup + offset, &decode); + width = decode.len; + //_assert(width != 0 && offset + width <= used); + +#ifdef __LP64__ + if ((decode.modrm & 0xc7) == 0x05) { + if (decode.opcode == 0x8b) { + void *destiny(area + offset + width + int32_t(decode.disp.disp32)); + uint8_t reg(decode.rex_r << 3 | decode.modrm_reg); + MSPushPointer(current, destiny); + MSWritePop(current, reg); + MSWriteMove64(current, reg, reg); + } else { + MSLog(MSLogLevelError, "MS:Error: Unknown RIP-Relative (%.2x %.2x)", decode.opcode, decode.opcode2); + goto copy; + } + } else +#endif + + if (backup[offset] == 0xe8) { + int32_t relative(*reinterpret_cast(backup + offset + 1)); + if (relative == 0) + MSPushPointer(current, area + offset + decode.len); + else { + MSWrite(current, 0xe8); + MSWrite(current, MSSizeOfSkip()); + void *destiny(area + offset + decode.len + relative); + MSWriteSkip(current, MSSizeOfJump(destiny, current + MSSizeOfSkip())); + MSWriteJump(current, destiny); + } + } else if (backup[offset] == 0xeb) + MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + else if (backup[offset] == 0xe9) + MSWriteJump(current, area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + else if ( + backup[offset] == 0xe3 || + (backup[offset] & 0xf0) == 0x70 + ) { + MSWrite(current, backup[offset]); + MSWrite(current, 2); + MSWrite(current, 0xeb); + void *destiny(area + offset + decode.len + *reinterpret_cast(backup + offset + 1)); + MSWrite(current, MSSizeOfJump(destiny, current + 1)); + MSWriteJump(current, destiny); + } else +#ifdef __LP64__ + copy: +#endif + { + MSWrite(current, backup + offset, width); + } + } + + MSWriteJump(current, area + used); + } + + if (mprotect(buffer, length, PROT_READ | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect():%d", errno); + goto fail; + } + + *result = buffer; + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", *result); + MSLogHex(buffer, length, name); + } + + } + + { + SubstrateHookMemory code(process, area, used); + + uint8_t *current(area); + MSWriteJump(current, target); + for (unsigned offset(0); offset != blank; ++offset) + MSWrite(current, 0x90); + } + + if (MSDebug) { + char name[16]; + sprintf(name, "%p", area); + MSLogHex(area, used + sizeof(uint16_t), name); + } +} +#endif + +_extern void MSHookFunction(void *symbol, void *replace, void **result) { + SubstrateHookFunction(NULL, symbol, replace, result); +} + +#if defined(__APPLE__) && defined(__arm__) +_extern void _Z14MSHookFunctionPvS_PS_(void *symbol, void *replace, void **result) { + return MSHookFunction(symbol, replace, result); +} +#endif diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.h b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.h new file mode 100755 index 000000000..40a0296cb --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateHook.h @@ -0,0 +1,19 @@ +#ifndef __SUBSTRATEHOOK_H__ +#define __SUBSTRATEHOOK_H__ + + +#include + +#define _extern extern "C" __attribute__((__visibility__("default"))) + +#ifdef __cplusplus +extern "C" { +#endif + +void MSHookFunction(void *symbol, void *replace, void **result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateLog.hpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateLog.hpp new file mode 100755 index 000000000..3e5728014 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateLog.hpp @@ -0,0 +1,40 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_LOG_HPP +#define SUBSTRATE_LOG_HPP + +#if 0 +#include + +#define MSLog(level, format, ...) ((void)__android_log_print(level, "NNNN", format, __VA_ARGS__)) + +#define MSLogLevelNotice ANDROID_LOG_INFO +#define MSLogLevelWarning ANDROID_LOG_WARN +#define MSLogLevelError ANDROID_LOG_ERROR + +#else + +#define MSLog(level, format, ...) printf(format, __VA_ARGS__) + +#endif + +#endif//SUBSTRATE_LOG_HPP diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstratePosixMemory.cpp b/VirtualApp/lib/src/main/jni/Substrate/SubstratePosixMemory.cpp new file mode 100755 index 000000000..709cb228e --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstratePosixMemory.cpp @@ -0,0 +1,75 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#define SubstrateInternal +#include "CydiaSubstrate.h" +#include "SubstrateLog.hpp" + +#include + +#include +#include +#include + +extern "C" void __clear_cache (void *beg, void *end); + +struct __SubstrateMemory { + void *address_; + size_t width_; + + __SubstrateMemory(void *address, size_t width) : + address_(address), + width_(width) + { + } +}; + +extern "C" SubstrateMemoryRef SubstrateMemoryCreate(SubstrateAllocatorRef allocator, SubstrateProcessRef process, void *data, size_t size) { + if (allocator != NULL) { + MSLog(MSLogLevelError, "MS:Error:allocator != %d", 0); + return NULL; + } + + if (size == 0) + return NULL; + + long page(sysconf(_SC_PAGESIZE)); // Portable applications should employ sysconf(_SC_PAGESIZE) instead of getpagesize + + uintptr_t base(reinterpret_cast(data) / page * page); + size_t width(((reinterpret_cast(data) + size - 1) / page + 1) * page - base); + void *address(reinterpret_cast(base)); + + if (mprotect(address, width, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { + MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); + return NULL; + } + + return new __SubstrateMemory(address, width); +} + +extern "C" void SubstrateMemoryRelease(SubstrateMemoryRef memory) { + if (mprotect(memory->address_, memory->width_, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) + MSLog(MSLogLevelError, "MS:Error:mprotect() = %d", errno); + + __clear_cache(reinterpret_cast(memory->address_), reinterpret_cast(memory->address_) + memory->width_); + + delete memory; +} diff --git a/VirtualApp/lib/src/main/jni/Substrate/SubstrateX86.hpp b/VirtualApp/lib/src/main/jni/Substrate/SubstrateX86.hpp new file mode 100755 index 000000000..ffe2b06e3 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/SubstrateX86.hpp @@ -0,0 +1,200 @@ +/* Cydia Substrate - Powerful Code Insertion Platform + * Copyright (C) 2008-2011 Jay Freeman (saurik) +*/ + +/* GNU Lesser General Public License, Version 3 {{{ */ +/* + * Substrate is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Substrate is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Substrate. If not, see . +**/ +/* }}} */ + +#ifndef SUBSTRATE_X86_HPP +#define SUBSTRATE_X86_HPP + +#include "Buffer.hpp" + +#ifdef __LP64__ +static const bool ia32 = false; +#else +static const bool ia32 = true; +#endif + +enum I$r { + I$rax, I$rcx, I$rdx, I$rbx, + I$rsp, I$rbp, I$rsi, I$rdi, + I$r8, I$r9, I$r10, I$r11, + I$r12, I$r13, I$r14, I$r15, +}; + +_disused static bool MSIs32BitOffset(uintptr_t target, uintptr_t source) { + intptr_t offset(target - source); + return int32_t(offset) == offset; +} + +_disused static size_t MSSizeOfSkip() { + return 5; +} + +_disused static size_t MSSizeOfPushPointer(uintptr_t target) { + return uint64_t(target) >> 32 == 0 ? 5 : 13; +} + +_disused static size_t MSSizeOfPushPointer(void *target) { + return MSSizeOfPushPointer(reinterpret_cast(target)); +} + +_disused static size_t MSSizeOfJump(bool blind, uintptr_t target, uintptr_t source = 0) { + if (ia32 || !blind && MSIs32BitOffset(target, source + 5)) + return MSSizeOfSkip(); + else + return MSSizeOfPushPointer(target) + 1; +} + +_disused static size_t MSSizeOfJump(uintptr_t target, uintptr_t source) { + return MSSizeOfJump(false, target, source); +} + +_disused static size_t MSSizeOfJump(uintptr_t target) { + return MSSizeOfJump(true, target); +} + +_disused static size_t MSSizeOfJump(void *target, void *source) { + return MSSizeOfJump(reinterpret_cast(target), reinterpret_cast(source)); +} + +_disused static size_t MSSizeOfJump(void *target) { + return MSSizeOfJump(reinterpret_cast(target)); +} + +_disused static void MSWriteSkip(uint8_t *¤t, ssize_t size) { + MSWrite(current, 0xe9); + MSWrite(current, size); +} + +_disused static void MSPushPointer(uint8_t *¤t, uintptr_t target) { + MSWrite(current, 0x68); + MSWrite(current, target); + + if (uint32_t high = uint64_t(target) >> 32) { + MSWrite(current, 0xc7); + MSWrite(current, 0x44); + MSWrite(current, 0x24); + MSWrite(current, 0x04); + MSWrite(current, high); + } +} + +_disused static void MSPushPointer(uint8_t *¤t, void *target) { + return MSPushPointer(current, reinterpret_cast(target)); +} + +_disused static void MSWriteCall(uint8_t *¤t, I$r target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0xff); + MSWrite(current, 0xd0 | target & 0x07); +} + +_disused static void MSWriteCall(uint8_t *¤t, uintptr_t target) { + uintptr_t source(reinterpret_cast(current)); + + if (ia32 || MSIs32BitOffset(target, source + 5)) { + MSWrite(current, 0xe8); + MSWrite(current, target - (source + 5)); + } else { + MSPushPointer(current, target); + + MSWrite(current, 0x83); + MSWrite(current, 0xc4); + MSWrite(current, 0x08); + + MSWrite(current, 0x67); + MSWrite(current, 0xff); + MSWrite(current, 0x54); + MSWrite(current, 0x24); + MSWrite(current, 0xf8); + } +} + +template +_disused static void MSWriteCall(uint8_t *¤t, Type_ *target) { + return MSWriteCall(current, reinterpret_cast(target)); +} + +_disused static void MSWriteJump(uint8_t *¤t, uintptr_t target) { + uintptr_t source(reinterpret_cast(current)); + + if (ia32 || MSIs32BitOffset(target, source + 5)) + MSWriteSkip(current, target - (source + 5)); + else { + MSPushPointer(current, target); + MSWrite(current, 0xc3); + } +} + +_disused static void MSWriteJump(uint8_t *¤t, void *target) { + return MSWriteJump(current, reinterpret_cast(target)); +} + +_disused static void MSWriteJump(uint8_t *¤t, I$r target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0xff); + MSWrite(current, 0xe0 | target & 0x07); +} + +_disused static void MSWritePop(uint8_t *¤t, uint8_t target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0x58 | target & 0x07); +} + +_disused static size_t MSSizeOfPop(uint8_t target) { + return target >> 3 != 0 ? 2 : 1; +} + +_disused static void MSWritePush(uint8_t *¤t, I$r target) { + if (target >> 3 != 0) + MSWrite(current, 0x40 | (target & 0x08) >> 3); + MSWrite(current, 0x50 | target & 0x07); +} + +_disused static void MSWriteAdd(uint8_t *¤t, I$r target, uint8_t source) { + MSWrite(current, 0x83); + MSWrite(current, 0xc4 | target & 0x07); + MSWrite(current, source); +} + +_disused static void MSWriteSet64(uint8_t *¤t, I$r target, uintptr_t source) { + MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2); + MSWrite(current, 0xb8 | target & 0x7); + MSWrite(current, source); +} + +template +_disused static void MSWriteSet64(uint8_t *¤t, I$r target, Type_ *source) { + return MSWriteSet64(current, target, reinterpret_cast(source)); +} + +_disused static void MSWriteMove64(uint8_t *¤t, uint8_t source, uint8_t target) { + MSWrite(current, 0x48 | (target & 0x08) >> 3 << 2 | (source & 0x08) >> 3); + MSWrite(current, 0x8b); + MSWrite(current, (target & 0x07) << 3 | source & 0x07); +} + +_disused static size_t MSSizeOfMove64() { + return 3; +} + +#endif//SUBSTRATE_X86_HPP diff --git a/VirtualApp/lib/src/main/jni/Substrate/hde64.c b/VirtualApp/lib/src/main/jni/Substrate/hde64.c new file mode 100755 index 000000000..d69f0c68e --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/hde64.c @@ -0,0 +1,332 @@ +/* + * Hacker Disassembler Engine 64 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#include +#include + +#include "hde64.h" +#include "table64.h" + +unsigned int hde64_disasm(const void *code, hde64s *hs) +{ + uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; + uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; + uint8_t op64 = 0; + + memset(hs,0,sizeof(hde64s)); + char *tmp=(char*)hs; + + for (x = 16; x; x--) + switch (c = *p++) { + case 0xf3: + hs->p_rep = c; + pref |= PRE_F3; + break; + case 0xf2: + hs->p_rep = c; + pref |= PRE_F2; + break; + case 0xf0: + hs->p_lock = c; + pref |= PRE_LOCK; + break; + case 0x26: case 0x2e: case 0x36: + case 0x3e: case 0x64: case 0x65: + hs->p_seg = c; + pref |= PRE_SEG; + break; + case 0x66: + hs->p_66 = c; + pref |= PRE_66; + break; + case 0x67: + hs->p_67 = c; + pref |= PRE_67; + break; + default: + goto pref_done; + } + pref_done: + + hs->flags = (uint32_t)pref << 23; + + if (!pref) + pref |= PRE_NONE; + + if ((c & 0xf0) == 0x40) { + hs->flags |= F_PREFIX_REX; + if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) + op64++; + hs->rex_r = (c & 7) >> 2; + hs->rex_x = (c & 3) >> 1; + hs->rex_b = c & 1; + if (((c = *p++) & 0xf0) == 0x40) { + opcode = c; + goto error_opcode; + } + } + + if ((hs->opcode = c) == 0x0f) { + hs->opcode2 = c = *p++; + ht += DELTA_OPCODES; + } else if (c >= 0xa0 && c <= 0xa3) { + op64++; + if (pref & PRE_67) + pref |= PRE_66; + else + pref &= ~PRE_66; + } + + opcode = c; + cflags = ht[ht[opcode / 4] + (opcode % 4)]; + + if (cflags == C_ERROR) { + error_opcode: + hs->flags |= F_ERROR | F_ERROR_OPCODE; + cflags = 0; + if ((opcode & -3) == 0x24) + cflags++; + } + + x = 0; + if (cflags & C_GROUP) { + uint16_t t; + t = *(uint16_t *)(ht + (cflags & 0x7f)); + cflags = (uint8_t)t; + x = (uint8_t)(t >> 8); + } + + if (hs->opcode2) { + ht = hde64_table + DELTA_PREFIXES; + if (ht[ht[opcode / 4] + (opcode % 4)] & pref) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (cflags & C_MODRM) { + hs->flags |= F_MODRM; + hs->modrm = c = *p++; + hs->modrm_mod = m_mod = c >> 6; + hs->modrm_rm = m_rm = c & 7; + hs->modrm_reg = m_reg = (c & 0x3f) >> 3; + + if (x && ((x << m_reg) & 0x80)) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + + if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { + uint8_t t = opcode - 0xd9; + if (m_mod == 3) { + ht = hde64_table + DELTA_FPU_MODRM + t*8; + t = ht[m_reg] << m_rm; + } else { + ht = hde64_table + DELTA_FPU_REG; + t = ht[t] << m_reg; + } + if (t & 0x80) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (pref & PRE_LOCK) { + if (m_mod == 3) { + hs->flags |= F_ERROR | F_ERROR_LOCK; + } else { + uint8_t *table_end, op = opcode; + if (hs->opcode2) { + ht = hde64_table + DELTA_OP2_LOCK_OK; + table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; + } else { + ht = hde64_table + DELTA_OP_LOCK_OK; + table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; + op &= -2; + } + for (; ht != table_end; ht++) + if (*ht++ == op) { + if (!((*ht << m_reg) & 0x80)) + goto no_lock_error; + else + break; + } + hs->flags |= F_ERROR | F_ERROR_LOCK; + no_lock_error: + ; + } + } + + if (hs->opcode2) { + switch (opcode) { + case 0x20: case 0x22: + m_mod = 3; + if (m_reg > 4 || m_reg == 1) + goto error_operand; + else + goto no_error_operand; + case 0x21: case 0x23: + m_mod = 3; + if (m_reg == 4 || m_reg == 5) + goto error_operand; + else + goto no_error_operand; + } + } else { + switch (opcode) { + case 0x8c: + if (m_reg > 5) + goto error_operand; + else + goto no_error_operand; + case 0x8e: + if (m_reg == 1 || m_reg > 5) + goto error_operand; + else + goto no_error_operand; + } + } + + if (m_mod == 3) { + uint8_t *table_end; + if (hs->opcode2) { + ht = hde64_table + DELTA_OP2_ONLY_MEM; + table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; + } else { + ht = hde64_table + DELTA_OP_ONLY_MEM; + table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; + } + for (; ht != table_end; ht += 2) + if (*ht++ == opcode) { + if (*ht++ & pref && !((*ht << m_reg) & 0x80)) + goto error_operand; + else + break; + } + goto no_error_operand; + } else if (hs->opcode2) { + switch (opcode) { + case 0x50: case 0xd7: case 0xf7: + if (pref & (PRE_NONE | PRE_66)) + goto error_operand; + break; + case 0xd6: + if (pref & (PRE_F2 | PRE_F3)) + goto error_operand; + break; + case 0xc5: + goto error_operand; + } + goto no_error_operand; + } else + goto no_error_operand; + + error_operand: + hs->flags |= F_ERROR | F_ERROR_OPERAND; + no_error_operand: + + c = *p++; + if (m_reg <= 1) { + if (opcode == 0xf6) + cflags |= C_IMM8; + else if (opcode == 0xf7) + cflags |= C_IMM_P66; + } + + switch (m_mod) { + case 0: + if (pref & PRE_67) { + if (m_rm == 6) + disp_size = 2; + } else + if (m_rm == 5) + disp_size = 4; + break; + case 1: + disp_size = 1; + break; + case 2: + disp_size = 2; + if (!(pref & PRE_67)) + disp_size <<= 1; + } + + if (m_mod != 3 && m_rm == 4) { + hs->flags |= F_SIB; + p++; + hs->sib = c; + hs->sib_scale = c >> 6; + hs->sib_index = (c & 0x3f) >> 3; + if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) + disp_size = 4; + } + + p--; + switch (disp_size) { + case 1: + hs->flags |= F_DISP8; + hs->disp.disp8 = *p; + break; + case 2: + hs->flags |= F_DISP16; + hs->disp.disp16 = *(uint16_t *)p; + break; + case 4: + hs->flags |= F_DISP32; + hs->disp.disp32 = *(uint32_t *)p; + } + p += disp_size; + } else if (pref & PRE_LOCK) + hs->flags |= F_ERROR | F_ERROR_LOCK; + + if (cflags & C_IMM_P66) { + if (cflags & C_REL32) { + if (pref & PRE_66) { + hs->flags |= F_IMM16 | F_RELATIVE; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + goto disasm_done; + } + goto rel32_ok; + } + if (op64) { + hs->flags |= F_IMM64; + hs->imm.imm64 = *(uint64_t *)p; + p += 8; + } else if (!(pref & PRE_66)) { + hs->flags |= F_IMM32; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } else + goto imm16_ok; + } + + + if (cflags & C_IMM16) { + imm16_ok: + hs->flags |= F_IMM16; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + } + if (cflags & C_IMM8) { + hs->flags |= F_IMM8; + hs->imm.imm8 = *p++; + } + + if (cflags & C_REL32) { + rel32_ok: + hs->flags |= F_IMM32 | F_RELATIVE; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } else if (cflags & C_REL8) { + hs->flags |= F_IMM8 | F_RELATIVE; + hs->imm.imm8 = *p++; + } + + disasm_done: + + if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { + hs->flags |= F_ERROR | F_ERROR_LENGTH; + hs->len = 15; + } + + return (unsigned int)hs->len; +} diff --git a/VirtualApp/lib/src/main/jni/Substrate/hde64.h b/VirtualApp/lib/src/main/jni/Substrate/hde64.h new file mode 100755 index 000000000..2fcc4cb25 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/hde64.h @@ -0,0 +1,112 @@ +/* + * Hacker Disassembler Engine 64 + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + * hde64.h: C/C++ header file + * + */ + +#ifndef _HDE64_H_ +#define _HDE64_H_ + +/* stdint.h - C99 standard header + * http://en.wikipedia.org/wiki/stdint.h + * + * if your compiler doesn't contain "stdint.h" header (for + * example, Microsoft Visual C++), you can download file: + * http://www.azillionmonkeys.com/qed/pstdint.h + * and change next line to: + * #include "pstdint.h" + */ +#include + +#define F_MODRM 0x00000001 +#define F_SIB 0x00000002 +#define F_IMM8 0x00000004 +#define F_IMM16 0x00000008 +#define F_IMM32 0x00000010 +#define F_IMM64 0x00000020 +#define F_DISP8 0x00000040 +#define F_DISP16 0x00000080 +#define F_DISP32 0x00000100 +#define F_RELATIVE 0x00000200 +#define F_ERROR 0x00001000 +#define F_ERROR_OPCODE 0x00002000 +#define F_ERROR_LENGTH 0x00004000 +#define F_ERROR_LOCK 0x00008000 +#define F_ERROR_OPERAND 0x00010000 +#define F_PREFIX_REPNZ 0x01000000 +#define F_PREFIX_REPX 0x02000000 +#define F_PREFIX_REP 0x03000000 +#define F_PREFIX_66 0x04000000 +#define F_PREFIX_67 0x08000000 +#define F_PREFIX_LOCK 0x10000000 +#define F_PREFIX_SEG 0x20000000 +#define F_PREFIX_REX 0x40000000 +#define F_PREFIX_ANY 0x7f000000 + +#define PREFIX_SEGMENT_CS 0x2e +#define PREFIX_SEGMENT_SS 0x36 +#define PREFIX_SEGMENT_DS 0x3e +#define PREFIX_SEGMENT_ES 0x26 +#define PREFIX_SEGMENT_FS 0x64 +#define PREFIX_SEGMENT_GS 0x65 +#define PREFIX_LOCK 0xf0 +#define PREFIX_REPNZ 0xf2 +#define PREFIX_REPX 0xf3 +#define PREFIX_OPERAND_SIZE 0x66 +#define PREFIX_ADDRESS_SIZE 0x67 + +#pragma pack(push,1) + +typedef struct { + uint8_t len; + uint8_t p_rep; + uint8_t p_lock; + uint8_t p_seg; + uint8_t p_66; + uint8_t p_67; + uint8_t rex; + uint8_t rex_w; + uint8_t rex_r; + uint8_t rex_x; + uint8_t rex_b; + uint8_t opcode; + uint8_t opcode2; + uint8_t modrm; + uint8_t modrm_mod; + uint8_t modrm_reg; + uint8_t modrm_rm; + uint8_t sib; + uint8_t sib_scale; + uint8_t sib_index; + uint8_t sib_base; + union { + uint8_t imm8; + uint16_t imm16; + uint32_t imm32; + uint64_t imm64; + } imm; + union { + uint8_t disp8; + uint16_t disp16; + uint32_t disp32; + } disp; + uint32_t flags; +} hde64s; + +#pragma pack(pop) + +#ifdef __cplusplus +extern "C" { +#endif + +/* __cdecl */ +unsigned int hde64_disasm(const void *code, hde64s *hs); + +#ifdef __cplusplus +} +#endif + +#endif /* _HDE64_H_ */ diff --git a/VirtualApp/lib/src/main/jni/Substrate/table64.h b/VirtualApp/lib/src/main/jni/Substrate/table64.h new file mode 100755 index 000000000..144f29076 --- /dev/null +++ b/VirtualApp/lib/src/main/jni/Substrate/table64.h @@ -0,0 +1,74 @@ +/* + * Hacker Disassembler Engine 64 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#define C_NONE 0x00 +#define C_MODRM 0x01 +#define C_IMM8 0x02 +#define C_IMM16 0x04 +#define C_IMM_P66 0x10 +#define C_REL8 0x20 +#define C_REL32 0x40 +#define C_GROUP 0x80 +#define C_ERROR 0xff + +#define PRE_ANY 0x00 +#define PRE_NONE 0x01 +#define PRE_F2 0x02 +#define PRE_F3 0x04 +#define PRE_66 0x08 +#define PRE_67 0x10 +#define PRE_LOCK 0x20 +#define PRE_SEG 0x40 +#define PRE_ALL 0xff + +#define DELTA_OPCODES 0x4a +#define DELTA_FPU_REG 0xfd +#define DELTA_FPU_MODRM 0x104 +#define DELTA_PREFIXES 0x13c +#define DELTA_OP_LOCK_OK 0x1ae +#define DELTA_OP2_LOCK_OK 0x1c6 +#define DELTA_OP_ONLY_MEM 0x1d8 +#define DELTA_OP2_ONLY_MEM 0x1e7 + +unsigned char hde64_table[] = { + 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, + 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, + 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, + 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, + 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, + 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, + 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, + 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, + 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, + 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, + 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, + 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, + 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, + 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, + 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, + 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, + 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, + 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, + 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, + 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, + 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, + 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, + 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, + 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, + 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, + 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, + 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, + 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, + 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, + 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, + 0x00,0xf0,0x02,0x00 +}; From dbb66d9cb849f4977b7b9e9156f89b8863709ba0 Mon Sep 17 00:00:00 2001 From: asLody Date: Sun, 10 Dec 2017 12:38:14 +0800 Subject: [PATCH 019/334] Framework: using new ipc framework. --- .../lody/virtual/client/core/VirtualCore.java | 28 ++++-- .../virtual/client/ipc/VAccountManager.java | 20 ++--- .../virtual/client/ipc/VActivityManager.java | 13 +-- .../virtual/client/ipc/VDeviceManager.java | 25 ++---- .../virtual/client/ipc/VJobScheduler.java | 29 ++---- .../client/ipc/VNotificationManager.java | 13 +-- .../virtual/client/ipc/VPackageManager.java | 69 +++++++-------- .../client/ipc/VirtualLocationManager.java | 50 ++++------- .../client/ipc/VirtualStorageManager.java | 19 +--- .../lody/virtual/helper/ipcbus/IPCBus.java | 42 +++++++++ .../lody/virtual/helper/ipcbus/IPCMethod.java | 88 +++++++++++++++++++ .../virtual/helper/ipcbus/IPCSingleton.java | 26 ++++++ .../virtual/helper/ipcbus/IPCTranslator.java | 29 ++++++ .../virtual/helper/ipcbus/IServerCache.java | 11 +++ .../helper/ipcbus/ServerInterface.java | 48 ++++++++++ .../helper/ipcbus/TransformBinder.java | 34 +++++++ .../com/lody/virtual/os/VUserManager.java | 3 +- .../lody/virtual/server/BinderProvider.java | 29 +++--- 18 files changed, 393 insertions(+), 183 deletions(-) create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCSingleton.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCTranslator.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IServerCache.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/ServerInterface.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java index 2a9d7a4fc..2bd1bf8a9 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java @@ -16,6 +16,7 @@ import android.graphics.Bitmap; import android.os.Bundle; import android.os.ConditionVariable; +import android.os.IBinder; import android.os.Looper; import android.os.Process; import android.os.RemoteException; @@ -34,11 +35,16 @@ import com.lody.virtual.client.ipc.VPackageManager; import com.lody.virtual.client.stub.VASettings; import com.lody.virtual.helper.compat.BundleCompat; +import com.lody.virtual.helper.ipcbus.IPCBus; +import com.lody.virtual.helper.ipcbus.IPCSingleton; +import com.lody.virtual.helper.ipcbus.IServerCache; import com.lody.virtual.helper.utils.BitmapUtils; import com.lody.virtual.os.VUserHandle; import com.lody.virtual.remote.InstallResult; import com.lody.virtual.remote.InstalledAppInfo; import com.lody.virtual.server.IAppManager; +import com.lody.virtual.server.IJobScheduler; +import com.lody.virtual.server.ServiceCache; import com.lody.virtual.server.interfaces.IAppRequestListener; import com.lody.virtual.server.interfaces.IPackageObserver; import com.lody.virtual.server.interfaces.IUiCallback; @@ -82,7 +88,7 @@ public final class VirtualCore { */ private String processName; private ProcessType processType; - private IAppManager mService; + private IPCSingleton singleton = new IPCSingleton<>(IAppManager.class); private boolean isStartUp; private PackageInfo hostPkgInfo; private int systemPid; @@ -178,6 +184,17 @@ public void startup(Context context) throws Throwable { mainThread = ActivityThread.currentActivityThread.call(); unHookPackageManager = context.getPackageManager(); hostPkgInfo = unHookPackageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PROVIDERS); + IPCBus.initialize(new IServerCache() { + @Override + public void join(String serverName, IBinder binder) { + ServiceCache.addService(serverName, binder); + } + + @Override + public IBinder query(String serverName) { + return ServiceManagerNative.getService(serverName); + } + }); detectProcessType(); InvocationStubManager invocationStubManager = InvocationStubManager.getInstance(); invocationStubManager.init(); @@ -252,14 +269,7 @@ private void detectProcessType() { } private IAppManager getService() { - if (mService == null - || (!VirtualCore.get().isVAppProcess() && !mService.asBinder().isBinderAlive())) { - synchronized (this) { - Object remote = getStubInterface(); - mService = LocalProxyUtils.genProxy(IAppManager.class, remote); - } - } - return mService; + return singleton.get(); } private Object getStubInterface() { diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java index 084adaf37..6554cb22d 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java @@ -13,8 +13,11 @@ import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.client.stub.AmsTask; +import com.lody.virtual.helper.ipcbus.IPCBus; +import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.os.VUserHandle; import com.lody.virtual.server.IAccountManager; +import com.lody.virtual.server.IActivityManager; import static com.lody.virtual.helper.compat.AccountManagerCompat.KEY_ANDROID_PACKAGE_NAME; @@ -26,26 +29,14 @@ public class VAccountManager { private static VAccountManager sMgr = new VAccountManager(); - private IAccountManager mRemote; + private IPCSingleton singleton = new IPCSingleton<>(IAccountManager.class); public static VAccountManager get() { return sMgr; } public IAccountManager getRemote() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (VAccountManager.class) { - Object remote = getStubInterface(); - mRemote = LocalProxyUtils.genProxy(IAccountManager.class, remote); - } - } - return mRemote; - } - - private Object getStubInterface() { - return IAccountManager.Stub - .asInterface(ServiceManagerNative.getService(ServiceManagerNative.ACCOUNT)); + return singleton.get(); } public AuthenticatorDescription[] getAuthenticatorTypes() { @@ -265,7 +256,6 @@ public String getUserData(Account account, String key) { *

This method may be called from any thread, but the returned * {@link AccountManagerFuture} must not be used on the main thread. *

- * */ public AccountManagerFuture addAccount(final int userId, final String accountType, final String authTokenType, final String[] requiredFeatures, diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java index c9ab8e09f..b796a82be 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java @@ -18,6 +18,8 @@ import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.client.hook.secondary.ServiceConnectionDelegate; import com.lody.virtual.helper.compat.ActivityManagerCompat; +import com.lody.virtual.helper.ipcbus.IPCBus; +import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.helper.utils.ComponentUtils; import com.lody.virtual.os.VUserHandle; import com.lody.virtual.remote.AppTaskInfo; @@ -42,21 +44,14 @@ public class VActivityManager { private static final VActivityManager sAM = new VActivityManager(); private final Map mActivities = new HashMap(6); - private IActivityManager mRemote; + private IPCSingleton singleton = new IPCSingleton<>(IActivityManager.class); public static VActivityManager get() { return sAM; } public IActivityManager getService() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (VActivityManager.class) { - final Object remote = getRemoteInterface(); - mRemote = LocalProxyUtils.genProxy(IActivityManager.class, remote); - } - } - return mRemote; + return singleton.get(); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java index 680037efe..e8654f92b 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java @@ -1,10 +1,9 @@ package com.lody.virtual.client.ipc; -import android.os.IBinder; import android.os.RemoteException; -import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.VirtualRuntime; +import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.remote.VDeviceInfo; import com.lody.virtual.server.IDeviceInfoManager; @@ -15,7 +14,7 @@ public class VDeviceManager { private static final VDeviceManager sInstance = new VDeviceManager(); - private IDeviceInfoManager mRemote; + private IPCSingleton singleton = new IPCSingleton<>(IDeviceInfoManager.class); public static VDeviceManager get() { @@ -23,27 +22,15 @@ public static VDeviceManager get() { } - public IDeviceInfoManager getRemote() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (this) { - Object remote = getRemoteInterface(); - mRemote = LocalProxyUtils.genProxy(IDeviceInfoManager.class, remote); - } - } - return mRemote; - } - - private Object getRemoteInterface() { - final IBinder binder = ServiceManagerNative.getService(ServiceManagerNative.DEVICE); - return IDeviceInfoManager.Stub.asInterface(binder); + public IDeviceInfoManager getService() { + return singleton.get(); } public VDeviceInfo getDeviceInfo(int userId) { try { - return getRemote().getDeviceInfo(userId); + return getService().getDeviceInfo(userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } } -} +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java index d51de1732..c22bd7f69 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java @@ -1,11 +1,10 @@ package com.lody.virtual.client.ipc; import android.app.job.JobInfo; -import android.os.IBinder; import android.os.RemoteException; -import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.VirtualRuntime; +import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.server.IJobScheduler; import java.util.List; @@ -18,31 +17,19 @@ public class VJobScheduler { private static final VJobScheduler sInstance = new VJobScheduler(); - private IJobScheduler mRemote; + private IPCSingleton singleton = new IPCSingleton<>(IJobScheduler.class); public static VJobScheduler get() { return sInstance; } - public IJobScheduler getRemote() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (this) { - Object remote = getRemoteInterface(); - mRemote = LocalProxyUtils.genProxy(IJobScheduler.class, remote); - } - } - return mRemote; - } - - private Object getRemoteInterface() { - final IBinder binder = ServiceManagerNative.getService(ServiceManagerNative.JOB); - return IJobScheduler.Stub.asInterface(binder); + public IJobScheduler getService() { + return singleton.get(); } public int schedule(JobInfo job) { try { - return getRemote().schedule(job); + return getService().schedule(job); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -50,7 +37,7 @@ public int schedule(JobInfo job) { public List getAllPendingJobs() { try { - return getRemote().getAllPendingJobs(); + return getService().getAllPendingJobs(); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -58,7 +45,7 @@ public List getAllPendingJobs() { public void cancelAll() { try { - getRemote().cancelAll(); + getService().cancelAll(); } catch (RemoteException e) { e.printStackTrace(); } @@ -66,7 +53,7 @@ public void cancelAll() { public void cancel(int jobId) { try { - getRemote().cancel(jobId); + getService().cancel(jobId); } catch (RemoteException e) { e.printStackTrace(); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java index a1402e0c8..653044d77 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java @@ -5,6 +5,8 @@ import android.os.RemoteException; import com.lody.virtual.client.core.VirtualCore; +import com.lody.virtual.helper.ipcbus.IPCSingleton; +import com.lody.virtual.server.IJobScheduler; import com.lody.virtual.server.INotificationManager; import com.lody.virtual.server.notification.NotificationCompat; @@ -14,7 +16,7 @@ public class VNotificationManager { private static final VNotificationManager sInstance = new VNotificationManager(); private final NotificationCompat mNotificationCompat; - private INotificationManager mRemote; + private IPCSingleton singleton = new IPCSingleton<>(INotificationManager.class); private VNotificationManager() { mNotificationCompat = NotificationCompat.create(); @@ -25,14 +27,7 @@ public static VNotificationManager get() { } public INotificationManager getService() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (VNotificationManager.class) { - final IBinder pmBinder = ServiceManagerNative.getService(ServiceManagerNative.NOTIFICATION); - mRemote = INotificationManager.Stub.asInterface(pmBinder); - } - } - return mRemote; + return singleton.get(); } public boolean dealNotification(int id, Notification notification, String packageName) { diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java index 317b0180e..d3e0ad136 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java @@ -13,8 +13,8 @@ import android.os.IBinder; import android.os.RemoteException; -import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.VirtualRuntime; +import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.server.IPackageInstaller; import com.lody.virtual.server.IPackageManager; @@ -26,21 +26,14 @@ public class VPackageManager { private static final VPackageManager sMgr = new VPackageManager(); - private IPackageManager mRemote; + private IPCSingleton singleton = new IPCSingleton<>(IPackageManager.class); public static VPackageManager get() { return sMgr; } - public IPackageManager getInterface() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (VPackageManager.class) { - Object remote = getRemoteInterface(); - mRemote = LocalProxyUtils.genProxy(IPackageManager.class, remote); - } - } - return mRemote; + public IPackageManager getService() { + return singleton.get(); } private Object getRemoteInterface() { @@ -50,7 +43,7 @@ private Object getRemoteInterface() { public int checkPermission(String permName, String pkgName, int userId) { try { - return getInterface().checkPermission(permName, pkgName, userId); + return getService().checkPermission(permName, pkgName, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -58,7 +51,7 @@ public int checkPermission(String permName, String pkgName, int userId) { public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) { try { - return getInterface().resolveService(intent, resolvedType, flags, userId); + return getService().resolveService(intent, resolvedType, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -66,7 +59,7 @@ public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) { try { - return getInterface().getPermissionGroupInfo(name, flags); + return getService().getPermissionGroupInfo(name, flags); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -75,7 +68,7 @@ public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) { public List getInstalledApplications(int flags, int userId) { try { // noinspection unchecked - return getInterface().getInstalledApplications(flags, userId).getList(); + return getService().getInstalledApplications(flags, userId).getList(); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -83,7 +76,7 @@ public List getInstalledApplications(int flags, int userId) { public PackageInfo getPackageInfo(String packageName, int flags, int userId) { try { - return getInterface().getPackageInfo(packageName, flags, userId); + return getService().getPackageInfo(packageName, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -91,7 +84,7 @@ public PackageInfo getPackageInfo(String packageName, int flags, int userId) { public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { try { - return getInterface().resolveIntent(intent, resolvedType, flags, userId); + return getService().resolveIntent(intent, resolvedType, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -99,7 +92,7 @@ public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, public List queryIntentContentProviders(Intent intent, String resolvedType, int flags, int userId) { try { - return getInterface().queryIntentContentProviders(intent, resolvedType, flags, userId); + return getService().queryIntentContentProviders(intent, resolvedType, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -107,7 +100,7 @@ public List queryIntentContentProviders(Intent intent, String resol public ActivityInfo getReceiverInfo(ComponentName componentName, int flags, int userId) { try { - return getInterface().getReceiverInfo(componentName, flags, userId); + return getService().getReceiverInfo(componentName, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -115,7 +108,7 @@ public ActivityInfo getReceiverInfo(ComponentName componentName, int flags, int public List getInstalledPackages(int flags, int userId) { try { - return getInterface().getInstalledPackages(flags, userId).getList(); + return getService().getInstalledPackages(flags, userId).getList(); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -123,7 +116,7 @@ public List getInstalledPackages(int flags, int userId) { public List queryPermissionsByGroup(String group, int flags) { try { - return getInterface().queryPermissionsByGroup(group, flags); + return getService().queryPermissionsByGroup(group, flags); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -131,7 +124,7 @@ public List queryPermissionsByGroup(String group, int flags) { public PermissionInfo getPermissionInfo(String name, int flags) { try { - return getInterface().getPermissionInfo(name, flags); + return getService().getPermissionInfo(name, flags); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -139,7 +132,7 @@ public PermissionInfo getPermissionInfo(String name, int flags) { public ActivityInfo getActivityInfo(ComponentName componentName, int flags, int userId) { try { - return getInterface().getActivityInfo(componentName, flags, userId); + return getService().getActivityInfo(componentName, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -147,7 +140,7 @@ public ActivityInfo getActivityInfo(ComponentName componentName, int flags, int public List queryIntentReceivers(Intent intent, String resolvedType, int flags, int userId) { try { - return getInterface().queryIntentReceivers(intent, resolvedType, flags, userId); + return getService().queryIntentReceivers(intent, resolvedType, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -155,7 +148,7 @@ public List queryIntentReceivers(Intent intent, String resolvedType public List getAllPermissionGroups(int flags) { try { - return getInterface().getAllPermissionGroups(flags); + return getService().getAllPermissionGroups(flags); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -163,7 +156,7 @@ public List getAllPermissionGroups(int flags) { public List queryIntentActivities(Intent intent, String resolvedType, int flags, int userId) { try { - return getInterface().queryIntentActivities(intent, resolvedType, flags, userId); + return getService().queryIntentActivities(intent, resolvedType, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -171,7 +164,7 @@ public List queryIntentActivities(Intent intent, String resolvedTyp public List queryIntentServices(Intent intent, String resolvedType, int flags, int userId) { try { - return getInterface().queryIntentServices(intent, resolvedType, flags, userId); + return getService().queryIntentServices(intent, resolvedType, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -179,7 +172,7 @@ public List queryIntentServices(Intent intent, String resolvedType, public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) { try { - return getInterface().getApplicationInfo(packageName, flags, userId); + return getService().getApplicationInfo(packageName, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -187,7 +180,7 @@ public ApplicationInfo getApplicationInfo(String packageName, int flags, int use public ProviderInfo resolveContentProvider(String name, int flags, int userId) { try { - return getInterface().resolveContentProvider(name, flags, userId); + return getService().resolveContentProvider(name, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -195,7 +188,7 @@ public ProviderInfo resolveContentProvider(String name, int flags, int userId) { public ServiceInfo getServiceInfo(ComponentName componentName, int flags, int userId) { try { - return getInterface().getServiceInfo(componentName, flags, userId); + return getService().getServiceInfo(componentName, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -203,7 +196,7 @@ public ServiceInfo getServiceInfo(ComponentName componentName, int flags, int us public ProviderInfo getProviderInfo(ComponentName componentName, int flags, int userId) { try { - return getInterface().getProviderInfo(componentName, flags, userId); + return getService().getProviderInfo(componentName, flags, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -211,7 +204,7 @@ public ProviderInfo getProviderInfo(ComponentName componentName, int flags, int public boolean activitySupportsIntent(ComponentName component, Intent intent, String resolvedType) { try { - return getInterface().activitySupportsIntent(component, intent, resolvedType); + return getService().activitySupportsIntent(component, intent, resolvedType); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -220,7 +213,7 @@ public boolean activitySupportsIntent(ComponentName component, Intent intent, St public List queryContentProviders(String processName, int uid, int flags) { try { // noinspection unchecked - return getInterface().queryContentProviders(processName, uid, flags).getList(); + return getService().queryContentProviders(processName, uid, flags).getList(); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -228,7 +221,7 @@ public List queryContentProviders(String processName, int uid, int public List querySharedPackages(String packageName) { try { - return getInterface().querySharedPackages(packageName); + return getService().querySharedPackages(packageName); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -236,7 +229,7 @@ public List querySharedPackages(String packageName) { public String[] getPackagesForUid(int uid) { try { - return getInterface().getPackagesForUid(uid); + return getService().getPackagesForUid(uid); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -244,7 +237,7 @@ public String[] getPackagesForUid(int uid) { public int getPackageUid(String packageName, int userId) { try { - return getInterface().getPackageUid(packageName, userId); + return getService().getPackageUid(packageName, userId); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -252,7 +245,7 @@ public int getPackageUid(String packageName, int userId) { public String getNameForUid(int uid) { try { - return getInterface().getNameForUid(uid); + return getService().getNameForUid(uid); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -261,7 +254,7 @@ public String getNameForUid(int uid) { public IPackageInstaller getPackageInstaller() { try { - return getInterface().getPackageInstaller(); + return getService().getPackageInstaller(); } catch (RemoteException e) { return VirtualRuntime.crash(e); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java index e9e5393f9..284d96057 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java @@ -1,11 +1,10 @@ package com.lody.virtual.client.ipc; -import android.os.IBinder; import android.os.RemoteException; -import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.client.hook.base.MethodProxy; +import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.remote.vloc.VCell; import com.lody.virtual.remote.vloc.VLocation; import com.lody.virtual.server.IVirtualLocationManager; @@ -19,7 +18,7 @@ public class VirtualLocationManager { private static final VirtualLocationManager sInstance = new VirtualLocationManager(); - private IVirtualLocationManager mRemote; + private IPCSingleton singleton = new IPCSingleton<>(IVirtualLocationManager.class); public static final int MODE_CLOSE = 0; public static final int MODE_USE_GLOBAL = 1; @@ -31,25 +30,14 @@ public static VirtualLocationManager get() { } - public IVirtualLocationManager getRemote() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (this) { - Object remote = getRemoteInterface(); - mRemote = LocalProxyUtils.genProxy(IVirtualLocationManager.class, remote); - } - } - return mRemote; + public IVirtualLocationManager getService() { + return singleton.get(); } - private Object getRemoteInterface() { - final IBinder binder = ServiceManagerNative.getService(ServiceManagerNative.VIRTUAL_LOC); - return IVirtualLocationManager.Stub.asInterface(binder); - } public int getMode(int userId, String pkg) { try { - return getRemote().getMode(userId, pkg); + return getService().getMode(userId, pkg); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -61,7 +49,7 @@ public int getMode() { public void setMode(int userId, String pkg, int mode) { try { - getRemote().setMode(userId, pkg, mode); + getService().setMode(userId, pkg, mode); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -69,7 +57,7 @@ public void setMode(int userId, String pkg, int mode) { public void setCell(int userId, String pkg, VCell cell) { try { - getRemote().setCell(userId, pkg, cell); + getService().setCell(userId, pkg, cell); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -77,7 +65,7 @@ public void setCell(int userId, String pkg, VCell cell) { public void setAllCell(int userId, String pkg, List cell) { try { - getRemote().setAllCell(userId, pkg, cell); + getService().setAllCell(userId, pkg, cell); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -85,7 +73,7 @@ public void setAllCell(int userId, String pkg, List cell) { public void setNeighboringCell(int userId, String pkg, List cell) { try { - getRemote().setNeighboringCell(userId, pkg, cell); + getService().setNeighboringCell(userId, pkg, cell); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -93,7 +81,7 @@ public void setNeighboringCell(int userId, String pkg, List cell) { public VCell getCell(int userId, String pkg) { try { - return getRemote().getCell(userId, pkg); + return getService().getCell(userId, pkg); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -101,7 +89,7 @@ public VCell getCell(int userId, String pkg) { public List getAllCell(int userId, String pkg) { try { - return getRemote().getAllCell(userId, pkg); + return getService().getAllCell(userId, pkg); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -109,7 +97,7 @@ public List getAllCell(int userId, String pkg) { public List getNeighboringCell(int userId, String pkg) { try { - return getRemote().getNeighboringCell(userId, pkg); + return getService().getNeighboringCell(userId, pkg); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -118,7 +106,7 @@ public List getNeighboringCell(int userId, String pkg) { public void setGlobalCell(VCell cell) { try { - getRemote().setGlobalCell(cell); + getService().setGlobalCell(cell); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -126,7 +114,7 @@ public void setGlobalCell(VCell cell) { public void setGlobalAllCell(List cell) { try { - getRemote().setGlobalAllCell(cell); + getService().setGlobalAllCell(cell); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -134,7 +122,7 @@ public void setGlobalAllCell(List cell) { public void setGlobalNeighboringCell(List cell) { try { - getRemote().setGlobalNeighboringCell(cell); + getService().setGlobalNeighboringCell(cell); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -142,7 +130,7 @@ public void setGlobalNeighboringCell(List cell) { public void setLocation(int userId, String pkg, VLocation loc) { try { - getRemote().setLocation(userId, pkg, loc); + getService().setLocation(userId, pkg, loc); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -150,7 +138,7 @@ public void setLocation(int userId, String pkg, VLocation loc) { public VLocation getLocation(int userId, String pkg) { try { - return getRemote().getLocation(userId, pkg); + return getService().getLocation(userId, pkg); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -162,7 +150,7 @@ public VLocation getLocation() { public void setGlobalLocation(VLocation loc) { try { - getRemote().setGlobalLocation(loc); + getService().setGlobalLocation(loc); } catch (RemoteException e) { VirtualRuntime.crash(e); } @@ -170,7 +158,7 @@ public void setGlobalLocation(VLocation loc) { public VLocation getGlobalLocation() { try { - return getRemote().getGlobalLocation(); + return getService().getGlobalLocation(); } catch (RemoteException e) { return VirtualRuntime.crash(e); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java index 58f8844ec..c5389b686 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java @@ -1,11 +1,10 @@ package com.lody.virtual.client.ipc; -import android.os.IBinder; import android.os.RemoteException; -import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.VirtualRuntime; +import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.server.IVirtualStorageService; /** @@ -15,7 +14,7 @@ public class VirtualStorageManager { private static final VirtualStorageManager sInstance = new VirtualStorageManager(); - private IVirtualStorageService mRemote; + private IPCSingleton singleton = new IPCSingleton<>(IVirtualStorageService.class); public static VirtualStorageManager get() { @@ -24,19 +23,7 @@ public static VirtualStorageManager get() { public IVirtualStorageService getRemote() { - if (mRemote == null || - (!mRemote.asBinder().isBinderAlive() && !VirtualCore.get().isVAppProcess())) { - synchronized (this) { - Object remote = getRemoteInterface(); - mRemote = LocalProxyUtils.genProxy(IVirtualStorageService.class, remote); - } - } - return mRemote; - } - - private Object getRemoteInterface() { - final IBinder binder = ServiceManagerNative.getService(ServiceManagerNative.VS); - return IVirtualStorageService.Stub.asInterface(binder); + return singleton.get(); } public void setVirtualStorage(String packageName, int userId, String vsPath) { diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java new file mode 100644 index 000000000..4fb65cb57 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java @@ -0,0 +1,42 @@ +package com.lody.virtual.helper.ipcbus; + + +import android.os.IBinder; + +import java.lang.reflect.Proxy; + +/** + * @author Lody + */ +public class IPCBus { + + private static IServerCache sCache; + + public static void initialize(IServerCache cache) { + sCache = cache; + } + + private static void checkInitialized() { + if (sCache == null) { + throw new IllegalStateException("please call initialize() at first."); + } + } + + public static void register(Class interfaceClass, Object server) { + checkInitialized(); + ServerInterface serverInterface = new ServerInterface(interfaceClass); + TransformBinder binder = new TransformBinder(serverInterface, server); + sCache.join(serverInterface.getInterfaceName(), binder); + } + + public static T get(Class interfaceClass) { + checkInitialized(); + ServerInterface serverInterface = new ServerInterface(interfaceClass); + IBinder binder = sCache.query(serverInterface.getInterfaceName()); + if (binder == null) { + return null; + } + //noinspection unchecked + return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new IPCTranslator(serverInterface, binder)); + } +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java new file mode 100644 index 000000000..0c42ef8f6 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java @@ -0,0 +1,88 @@ +package com.lody.virtual.helper.ipcbus; + +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.RemoteException; + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * @author Lody + */ +public class IPCMethod { + + private int code; + private Method method; + private String interfaceName; + + public IPCMethod(int code, Method method, String interfaceName) { + this.code = code; + this.method = method; + this.interfaceName = interfaceName; + } + + public String getInterfaceName() { + return interfaceName; + } + + public Method getMethod() { + return method; + } + + public void handleTransact(Object server, Parcel data, Parcel reply) { + data.enforceInterface(interfaceName); + Object[] parameters = data.readArray(getClass().getClassLoader()); + Object res = null; + try { + res = method.invoke(server, parameters); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + reply.writeNoException(); + reply.writeValue(res); + } + + public Object callRemote(IBinder server, Object[] args) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + Object result; + try { + data.writeInterfaceToken(interfaceName); + data.writeArray(args); + server.transact(code, data, reply, 0); + reply.readException(); + result = readValue(reply); + } finally { + data.recycle(); + reply.recycle(); + } + return result; + } + + private Object readValue(Parcel replay) { + Object result = replay.readValue(getClass().getClassLoader()); + if (result instanceof Parcelable[]) { + Parcelable[] parcelables = (Parcelable[]) result; + Object[] results = (Object[]) Array.newInstance(method.getReturnType().getComponentType(), parcelables.length); + System.arraycopy(parcelables, 0, results, 0, results.length); + return results; + } + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + IPCMethod ipcMethod = (IPCMethod) o; + + return method != null ? method.equals(ipcMethod.method) : ipcMethod.method == null; + } + +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCSingleton.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCSingleton.java new file mode 100644 index 000000000..56c3f00c1 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCSingleton.java @@ -0,0 +1,26 @@ +package com.lody.virtual.helper.ipcbus; + +/** + * @author Lody + */ +public class IPCSingleton { + + private Class ipcClass; + private T instance; + + public IPCSingleton(Class ipcClass) { + this.ipcClass = ipcClass; + } + + public T get() { + if (instance == null) { + synchronized (this) { + if (instance == null) { + instance = IPCBus.get(ipcClass); + } + } + } + return instance; + } + +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCTranslator.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCTranslator.java new file mode 100644 index 000000000..4121ccc65 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCTranslator.java @@ -0,0 +1,29 @@ +package com.lody.virtual.helper.ipcbus; + +import android.os.IBinder; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * @author Lody + */ +public class IPCTranslator implements InvocationHandler { + + private ServerInterface serverInterface; + private IBinder binder; + + public IPCTranslator(ServerInterface serverInterface, IBinder binder) { + this.serverInterface = serverInterface; + this.binder = binder; + } + + @Override + public Object invoke(Object o, Method method, Object[] args) throws Throwable { + IPCMethod ipcMethod = serverInterface.getIPCMethod(method); + if (ipcMethod == null) { + throw new IllegalStateException("Can not found the ipc method : " + method.getDeclaringClass().getName() + "@" + method.getName()); + } + return ipcMethod.callRemote(binder, args); + } +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IServerCache.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IServerCache.java new file mode 100644 index 000000000..63d3c8cd6 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IServerCache.java @@ -0,0 +1,11 @@ +package com.lody.virtual.helper.ipcbus; + +import android.os.IBinder; + +/** + * @author Lody + */ +public interface IServerCache { + void join(String serverName, IBinder binder); + IBinder query(String serverName); +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/ServerInterface.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/ServerInterface.java new file mode 100644 index 000000000..103f039cf --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/ServerInterface.java @@ -0,0 +1,48 @@ +package com.lody.virtual.helper.ipcbus; + +import android.os.Binder; + +import com.lody.virtual.helper.collection.SparseArray; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Lody + */ +public class ServerInterface { + + private Class interfaceClass; + private final SparseArray codeToInterfaceMethod; + private final Map methodToIPCMethodMap; + + public ServerInterface(Class interfaceClass) { + this.interfaceClass = interfaceClass; + Method[] methods = interfaceClass.getMethods(); + codeToInterfaceMethod = new SparseArray<>(methods.length); + methodToIPCMethodMap = new HashMap<>(methods.length); + for (int i = 0; i < methods.length; i++) { + int code = Binder.FIRST_CALL_TRANSACTION + i; + IPCMethod ipcMethod = new IPCMethod(code, methods[i], interfaceClass.getName()); + codeToInterfaceMethod.put(code, ipcMethod); + methodToIPCMethodMap.put(methods[i], ipcMethod); + } + } + + public Class getInterfaceClass() { + return interfaceClass; + } + + public String getInterfaceName() { + return interfaceClass.getName(); + } + + public IPCMethod getIPCMethod(int code) { + return codeToInterfaceMethod.get(code); + } + + public IPCMethod getIPCMethod(Method method) { + return methodToIPCMethodMap.get(method); + } +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java new file mode 100644 index 000000000..68444c578 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java @@ -0,0 +1,34 @@ +package com.lody.virtual.helper.ipcbus; + +import android.os.Binder; +import android.os.Parcel; +import android.os.RemoteException; + + +/** + * @author Lody + */ +public class TransformBinder extends Binder { + + private ServerInterface serverInterface; + private Object server; + + public TransformBinder(ServerInterface serverInterface, Object server) { + this.serverInterface = serverInterface; + this.server = server; + } + + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { + if (code == INTERFACE_TRANSACTION) { + reply.writeString(serverInterface.getInterfaceName()); + return true; + } + IPCMethod method = serverInterface.getIPCMethod(code); + if (method != null) { + method.handleTransact(server, data, reply); + return true; + } + return super.onTransact(code, data, reply, flags); + } +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java index aeef66ccb..fbf04fd92 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java @@ -5,6 +5,7 @@ import android.util.Log; import com.lody.virtual.client.ipc.ServiceManagerNative; +import com.lody.virtual.helper.ipcbus.IPCBus; import com.lody.virtual.server.IUserManager; import java.util.List; @@ -108,7 +109,7 @@ public class VUserManager { /** @hide */ public synchronized static VUserManager get() { if (sInstance == null) { - IUserManager remote = IUserManager.Stub.asInterface(ServiceManagerNative.getService(USER)); + IUserManager remote = IPCBus.get(IUserManager.class); sInstance = new VUserManager(remote); } return sInstance; diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java index 327ce44a4..16b446a43 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java @@ -14,6 +14,7 @@ import com.lody.virtual.client.ipc.ServiceManagerNative; import com.lody.virtual.client.stub.DaemonService; import com.lody.virtual.helper.compat.BundleCompat; +import com.lody.virtual.helper.ipcbus.IPCBus; import com.lody.virtual.server.accounts.VAccountManagerService; import com.lody.virtual.server.am.BroadcastSystem; import com.lody.virtual.server.am.VActivityManagerService; @@ -42,38 +43,36 @@ public boolean onCreate() { return true; } VPackageManagerService.systemReady(); - addService(ServiceManagerNative.PACKAGE, VPackageManagerService.get()); + IPCBus.register(IPackageManager.class, VPackageManagerService.get()); VActivityManagerService.systemReady(context); - addService(ServiceManagerNative.ACTIVITY, VActivityManagerService.get()); - addService(ServiceManagerNative.USER, VUserManagerService.get()); + IPCBus.register(IActivityManager.class, VActivityManagerService.get()); + IPCBus.register(IUserManager.class, VUserManagerService.get()); VAppManagerService.systemReady(); - addService(ServiceManagerNative.APP, VAppManagerService.get()); + IPCBus.register(IAppManager.class, VAppManagerService.get()); BroadcastSystem.attach(VActivityManagerService.get(), VAppManagerService.get()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - addService(ServiceManagerNative.JOB, VJobSchedulerService.get()); + IPCBus.register(IJobScheduler.class, VJobSchedulerService.get()); } VNotificationManagerService.systemReady(context); - addService(ServiceManagerNative.NOTIFICATION, VNotificationManagerService.get()); + IPCBus.register(INotificationManager.class, VNotificationManagerService.get()); VAppManagerService.get().scanApps(); VAccountManagerService.systemReady(); - addService(ServiceManagerNative.ACCOUNT, VAccountManagerService.get()); - addService(ServiceManagerNative.VS, VirtualStorageService.get()); - addService(ServiceManagerNative.DEVICE, VDeviceManagerService.get()); - addService(ServiceManagerNative.VIRTUAL_LOC, VirtualLocationService.get()); + IPCBus.register(IAccountManager.class, VAccountManagerService.get()); + IPCBus.register(IVirtualStorageService.class, VirtualStorageService.get()); + IPCBus.register(IDeviceInfoManager.class, VDeviceManagerService.get()); + IPCBus.register(IVirtualLocationManager.class, VirtualLocationService.get()); return true; } - - private void addService(String name, IBinder service) { - ServiceCache.addService(name, service); - } - @Override public Bundle call(String method, String arg, Bundle extras) { if ("@".equals(method)) { Bundle bundle = new Bundle(); BundleCompat.putBinder(bundle, "_VA_|_binder_", mServiceFetcher); return bundle; + } + if ("register".equals(method)) { + } return null; } From cf309b7c4abd9179660d42f91e3f9bf75184bdbe Mon Sep 17 00:00:00 2001 From: asLody Date: Sun, 10 Dec 2017 16:02:56 +0800 Subject: [PATCH 020/334] Framework: remove aidl files, instead of Interface. --- .../lody/virtual/server/IAccountManager.aidl | 47 ------- .../lody/virtual/server/IActivityManager.aidl | 116 ------------------ .../com/lody/virtual/server/IAppManager.aidl | 35 ------ .../virtual/server/IDeviceInfoManager.aidl | 12 -- .../lody/virtual/server/IJobScheduler.aidl | 13 -- .../virtual/server/INotificationManager.aidl | 14 --- .../lody/virtual/server/IPackageManager.aidl | 78 ------------ .../com/lody/virtual/server/IUserManager.aidl | 23 ---- .../server/IVirtualLocationManager.aidl | 30 ----- .../server/IVirtualStorageService.aidl | 15 --- .../lody/virtual/client/core/VirtualCore.java | 9 +- .../virtual/client/ipc/VAccountManager.java | 59 +++++---- .../virtual/client/ipc/VActivityManager.java | 26 +--- .../virtual/client/ipc/VDeviceManager.java | 2 +- .../virtual/client/ipc/VJobScheduler.java | 6 +- .../client/ipc/VNotificationManager.java | 6 +- .../virtual/client/ipc/VPackageManager.java | 12 +- .../client/ipc/VirtualLocationManager.java | 2 +- .../client/ipc/VirtualStorageManager.java | 2 +- .../lody/virtual/helper/ipcbus/IPCBus.java | 2 +- ...anslator.java => IPCInvocationBridge.java} | 4 +- .../lody/virtual/helper/ipcbus/IPCMethod.java | 94 +++++++++++++- .../helper/ipcbus/TransformBinder.java | 6 +- .../com/lody/virtual/os/VUserManager.java | 5 +- .../lody/virtual/server/BinderProvider.java | 12 +- .../accounts/VAccountManagerService.java | 14 +-- .../server/am/VActivityManagerService.java | 38 ++---- .../server/device/VDeviceManagerService.java | 8 +- .../server/interfaces/IAccountManager.java | 61 +++++++++ .../server/interfaces/IActivityManager.java | 106 ++++++++++++++++ .../server/interfaces/IAppManager.java | 58 +++++++++ .../server/interfaces/IDeviceInfoManager.java | 16 +++ .../server/interfaces/IJobService.java | 20 +++ .../interfaces/INotificationManager.java | 21 ++++ .../server/interfaces/IPackageManager.java | 72 +++++++++++ .../server/interfaces/IUserManager.java | 37 ++++++ .../interfaces/IVirtualLocationManager.java | 44 +++++++ .../interfaces/IVirtualStorageService.java | 17 +++ .../server/job/VJobSchedulerService.java | 13 +- .../location/VirtualLocationService.java | 34 ++--- .../VNotificationManagerService.java | 4 +- .../virtual/server/pm/VAppManagerService.java | 7 +- .../server/pm/VPackageManagerService.java | 22 +--- .../server/pm/VUserManagerService.java | 41 ++++--- .../server/vs/VirtualStorageService.java | 12 +- 45 files changed, 679 insertions(+), 596 deletions(-) delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAccountManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IActivityManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAppManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IDeviceInfoManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IJobScheduler.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/INotificationManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IPackageManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IUserManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualLocationManager.aidl delete mode 100644 VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualStorageService.aidl rename VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/{IPCTranslator.java => IPCInvocationBridge.java} (83%) create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAccountManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IActivityManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAppManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IDeviceInfoManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/INotificationManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IPackageManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IUserManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualLocationManager.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualStorageService.java diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAccountManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAccountManager.aidl deleted file mode 100644 index 0847ff426..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAccountManager.aidl +++ /dev/null @@ -1,47 +0,0 @@ -package com.lody.virtual.server; - -import android.accounts.IAccountManagerResponse; -import android.accounts.Account; -import android.accounts.AuthenticatorDescription; -import android.os.Bundle; - - -/** - * Central application service that provides account management. - * @hide - */ -interface IAccountManager { - AuthenticatorDescription[] getAuthenticatorTypes(int userId); - void getAccountsByFeatures(int userId, in IAccountManagerResponse response, in String type, in String[] features); - String getPreviousName(int userId, in Account account); - Account[] getAccounts(int userId, in String type); - void getAuthToken(int userId, in IAccountManagerResponse response, in Account account, in String authTokenType, in boolean notifyOnAuthFailure, in boolean expectActivityLaunch, in Bundle loginOptions); - void setPassword(int userId, in Account account, in String password); - void setAuthToken(int userId, in Account account, in String authTokenType, in String authToken); - void setUserData(int userId, in Account account, in String key, in String value); - void hasFeatures(int userId, in IAccountManagerResponse response, - in Account account, in String[] features); - void updateCredentials(int userId, in IAccountManagerResponse response, in Account account, - in String authTokenType, in boolean expectActivityLaunch, - in Bundle loginOptions); - void editProperties(int userId, in IAccountManagerResponse response, in String accountType, - in boolean expectActivityLaunch); - void getAuthTokenLabel(int userId, in IAccountManagerResponse response, in String accountType, - in String authTokenType); - String getUserData(int userId, in Account account, in String key); - String getPassword(int userId, in Account account); - void confirmCredentials(int userId, in IAccountManagerResponse response, in Account account, in Bundle options, in boolean expectActivityLaunch); - void addAccount(int userId, in IAccountManagerResponse response, in String accountType, - in String authTokenType, in String[] requiredFeatures, - in boolean expectActivityLaunch, in Bundle optionsIn); - boolean addAccountExplicitly(int userId, in Account account, in String password, in Bundle extras); - boolean removeAccountExplicitly(int userId, in Account account); - void renameAccount(int userId, in IAccountManagerResponse response, in Account accountToRename, in String newName); - void removeAccount(in int userId, in IAccountManagerResponse response, in Account account, - in boolean expectActivityLaunch); - void clearPassword(int userId, in Account account); - boolean accountAuthenticated(int userId, in Account account); - void invalidateAuthToken(int userId, in String accountType, in String authToken); - String peekAuthToken(int userId, in Account account, in String authTokenType); - -} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IActivityManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IActivityManager.aidl deleted file mode 100644 index 94d8625b5..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IActivityManager.aidl +++ /dev/null @@ -1,116 +0,0 @@ -// IActivityManager.aidl -package com.lody.virtual.server; - -import com.lody.virtual.remote.VParceledListSlice; -import com.lody.virtual.remote.AppTaskInfo; -import com.lody.virtual.remote.PendingIntentData; -import com.lody.virtual.remote.PendingResultData; -import com.lody.virtual.remote.BadgerInfo; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.app.Notification; -import android.app.IServiceConnection; -import android.app.IActivityManager.ContentProviderHolder; -import com.lody.virtual.server.interfaces.IProcessObserver; - - -interface IActivityManager { - - int initProcess(in String packageName, in String processName, int userId); - - int getFreeStubCount(); - - int getSystemPid(); - - int getUidByPid(int pid); - - boolean isAppProcess(String processName); - - boolean isAppRunning(String packageName, int userId); - - boolean isAppPid(int pid); - - String getAppProcessName(int pid); - - List getProcessPkgList(int pid); - - void killAllApps(); - - void killAppByPkg(String pkg, int userId); - - void killApplicationProcess(String procName, int vuid); - - void dump(); - - void registerProcessObserver(in IProcessObserver observer); - - void unregisterProcessObserver(in IProcessObserver observer); - - String getInitialPackage(int pid); - - void handleApplicationCrash(); - - void appDoneExecuting(); - - int startActivities(in Intent[] intents, in String[] resolvedTypes, in IBinder token, in Bundle options, in int userId); - - int startActivity(in Intent intent, in ActivityInfo info, in IBinder resultTo, in Bundle options, String resultWho, int requestCode, int userId); - - void onActivityCreated(in ComponentName component, in ComponentName caller, in IBinder token, in Intent intent, in String affinity, int taskId, int launchMode, int flags); - - void onActivityResumed(int userId, in IBinder token); - - boolean onActivityDestroyed(int userId, in IBinder token); - - ComponentName getActivityClassForToken(int userId, in IBinder token); - - String getCallingPackage(int userId, in IBinder token); - - ComponentName getCallingActivity(int userId, in IBinder token); - - AppTaskInfo getTaskInfo(int taskId); - - String getPackageForToken(int userId, in IBinder token); - - boolean isVAServiceToken(in IBinder token); - - ComponentName startService(in IBinder caller,in Intent service, String resolvedType, int userId); - - int stopService(in IBinder caller, in Intent service, String resolvedType, int userId); - - boolean stopServiceToken(in ComponentName className, in IBinder token, int startId, int userId); - - void setServiceForeground(in ComponentName className, in IBinder token, int id, - in Notification notification, boolean removeNotification, int userId); - - int bindService(in IBinder caller, in IBinder token, in Intent service, - String resolvedType, in IServiceConnection connection, int flags, int userId); - - boolean unbindService(in IServiceConnection connection, int userId); - - void unbindFinished(in IBinder token, in Intent service, in boolean doRebind, int userId); - - void serviceDoneExecuting(in IBinder token, in int type, in int startId, in int res, int userId); - - IBinder peekService(in Intent service, String resolvedType, int userId); - - void publishService(in IBinder token, in Intent intent, in IBinder service, int userId); - - VParceledListSlice getServices(int maxNum, int flags, int userId); - - IBinder acquireProviderClient(int userId, in ProviderInfo info); - - PendingIntentData getPendingIntent(IBinder binder); - - void addPendingIntent(IBinder binder, String packageName); - - void removePendingIntent(IBinder binder); - - String getPackageForIntentSender(IBinder binder); - - void processRestarted(in String packageName, in String processName, int userId); - - void broadcastFinish(in PendingResultData res); - - void notifyBadgerChange(in BadgerInfo info); -} diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAppManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAppManager.aidl deleted file mode 100644 index ca665ed60..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IAppManager.aidl +++ /dev/null @@ -1,35 +0,0 @@ -// IAppManager.aidl -package com.lody.virtual.server; - -import com.lody.virtual.server.interfaces.IPackageObserver; -import com.lody.virtual.server.interfaces.IAppRequestListener; -import com.lody.virtual.remote.InstalledAppInfo; -import com.lody.virtual.remote.InstallResult; - -interface IAppManager { - int[] getPackageInstalledUsers(String packageName); - void scanApps(); - void addVisibleOutsidePackage(String pkg); - void removeVisibleOutsidePackage(String pkg); - boolean isOutsidePackageVisible(String pkg); - InstalledAppInfo getInstalledAppInfo(String pkg, int flags); - InstallResult installPackage(String path, int flags); - boolean isPackageLaunched(int userId, String packageName); - void setPackageHidden(int userId, String packageName, boolean hidden); - boolean installPackageAsUser(int userId, String packageName); - boolean uninstallPackageAsUser(String packageName, int userId); - boolean uninstallPackage(String packageName); - List getInstalledApps(int flags); - List getInstalledAppsAsUser(int userId, int flags); - int getInstalledAppCount(); - boolean isAppInstalled(String packageName); - boolean isAppInstalledAsUser(int userId, String packageName); - - void registerObserver(IPackageObserver observer); - void unregisterObserver(IPackageObserver observer); - - void setAppRequestListener(IAppRequestListener listener); - void clearAppRequestListener(); - IAppRequestListener getAppRequestListener(); - -} diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IDeviceInfoManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IDeviceInfoManager.aidl deleted file mode 100644 index 3305d799d..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IDeviceInfoManager.aidl +++ /dev/null @@ -1,12 +0,0 @@ -// IDeviceInfoManager.aidl -package com.lody.virtual.server; - -import com.lody.virtual.remote.VDeviceInfo; - -interface IDeviceInfoManager { - - VDeviceInfo getDeviceInfo(int userId); - - void updateDeviceInfo(int userId, in VDeviceInfo info); - -} diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IJobScheduler.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IJobScheduler.aidl deleted file mode 100644 index 5e230364c..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IJobScheduler.aidl +++ /dev/null @@ -1,13 +0,0 @@ -package com.lody.virtual.server; - -import android.app.job.JobInfo; - - /** - * IPC interface that supports the app-facing {@link #JobScheduler} api. - */ -interface IJobScheduler { - int schedule(in JobInfo job); - void cancel(int jobId); - void cancelAll(); - List getAllPendingJobs(); -} diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/INotificationManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/INotificationManager.aidl deleted file mode 100644 index c48b2320d..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/INotificationManager.aidl +++ /dev/null @@ -1,14 +0,0 @@ -// INotificationManager.aidl -package com.lody.virtual.server; - -// Declare any non-default types here with import statements -import android.app.Notification; - -interface INotificationManager { - int dealNotificationId(int id, String packageName, String tag, int userId); - String dealNotificationTag(int id, String packageName, String tag, int userId); - boolean areNotificationsEnabledForPackage(String packageName, int userId); - void setNotificationsEnabledForPackage(String packageName, boolean enable, int userId); - void addNotification(int id, String tag, String packageName, int userId); - void cancelAllNotification(String packageName, int userId); -} diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IPackageManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IPackageManager.aidl deleted file mode 100644 index 973cbf7ef..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IPackageManager.aidl +++ /dev/null @@ -1,78 +0,0 @@ -// IPackageManager.aidl -package com.lody.virtual.server; - -import android.content.ComponentName; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.ActivityInfo; -import android.content.pm.ServiceInfo; -import android.content.pm.ProviderInfo; -import android.content.pm.ResolveInfo; -import android.content.pm.ApplicationInfo; -import android.content.IntentFilter; -import android.content.pm.PermissionInfo; -import android.content.pm.PermissionGroupInfo; - -import com.lody.virtual.remote.ReceiverInfo; -import com.lody.virtual.remote.VParceledListSlice; - -import com.lody.virtual.server.IPackageInstaller; - -interface IPackageManager { - - int getPackageUid(String packageName, int userId); - - String[] getPackagesForUid(int vuid); - - List getSharedLibraries(String pkgName); - - int checkPermission(String permName, String pkgName, int userId); - - PackageInfo getPackageInfo(String packageName, int flags, int userId); - - ActivityInfo getActivityInfo(in ComponentName componentName, int flags, int userId); - - boolean activitySupportsIntent(in ComponentName component, in Intent intent, - in String resolvedType); - ActivityInfo getReceiverInfo(in ComponentName componentName, int flags, int userId); - - ServiceInfo getServiceInfo(in ComponentName componentName, int flags, int userId); - - ProviderInfo getProviderInfo(in ComponentName componentName, int flags, int userId); - - ResolveInfo resolveIntent(in Intent intent, in String resolvedType, int flags, int userId); - - List queryIntentActivities(in Intent intent,in String resolvedType, int flags, int userId); - - List queryIntentReceivers(in Intent intent, String resolvedType, int flags, int userId); - - ResolveInfo resolveService(in Intent intent, String resolvedType, int flags, int userId); - - List queryIntentServices(in Intent intent, String resolvedType, int flags, int userId); - - List queryIntentContentProviders(in Intent intent, String resolvedType, int flags, int userId); - - VParceledListSlice getInstalledPackages(int flags, int userId); - - VParceledListSlice getInstalledApplications(int flags, int userId); - - PermissionInfo getPermissionInfo(in String name, int flags); - - List queryPermissionsByGroup(in String group, int flags); - - PermissionGroupInfo getPermissionGroupInfo(in String name, int flags); - - List getAllPermissionGroups(int flags); - - ProviderInfo resolveContentProvider(in String name, int flags, int userId); - - ApplicationInfo getApplicationInfo(in String packageName, int flags, int userId); - - VParceledListSlice queryContentProviders(in String processName, int vuid, int flags); - - List querySharedPackages(in String packageName); - - String getNameForUid(int uid); - - IPackageInstaller getPackageInstaller(); -} diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IUserManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IUserManager.aidl deleted file mode 100644 index 1f0faded3..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IUserManager.aidl +++ /dev/null @@ -1,23 +0,0 @@ -package com.lody.virtual.server; - -import android.os.ParcelFileDescriptor; -import com.lody.virtual.os.VUserInfo; -import android.graphics.Bitmap; - -/** -* - */ -interface IUserManager { - VUserInfo createUser(in String name, int flags); - boolean removeUser(int userHandle); - void setUserName(int userHandle, String name); - void setUserIcon(int userHandle, in Bitmap icon); - Bitmap getUserIcon(int userHandle); - List getUsers(boolean excludeDying); - VUserInfo getUserInfo(int userHandle); - void setGuestEnabled(boolean enable); - boolean isGuestEnabled(); - void wipeUser(int userHandle); - int getUserSerialNumber(int userHandle); - int getUserHandle(int userSerialNumber); -} diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualLocationManager.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualLocationManager.aidl deleted file mode 100644 index 750319aa8..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualLocationManager.aidl +++ /dev/null @@ -1,30 +0,0 @@ -// IVirtualLocationManager.aidl -package com.lody.virtual.server; - -import com.lody.virtual.remote.vloc.VCell; -import com.lody.virtual.remote.vloc.VWifi; -import com.lody.virtual.remote.vloc.VLocation; - -interface IVirtualLocationManager { - - int getMode(int userId, in String pkg); - void setMode(int userId, in String pkg, int mode); - - void setCell(in int userId, in String pkg, in VCell cell); - void setAllCell(in int userId, in String pkg, in List cell); - void setNeighboringCell(in int userId, in String pkg, in List cell); - - void setGlobalCell(in VCell cell); - void setGlobalAllCell(in List cell); - void setGlobalNeighboringCell(in List cell); - - VCell getCell(in int userId, in String pkg); - List getAllCell(in int userId, in String pkg); - List getNeighboringCell(in int userId, in String pkg); - - void setLocation(in int userId, in String pkg, in VLocation loc); - VLocation getLocation(in int userId, in String pkg); - - void setGlobalLocation(in VLocation loc); - VLocation getGlobalLocation(); -} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualStorageService.aidl b/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualStorageService.aidl deleted file mode 100644 index 042b8254b..000000000 --- a/VirtualApp/lib/src/main/aidl/com/lody/virtual/server/IVirtualStorageService.aidl +++ /dev/null @@ -1,15 +0,0 @@ -// IVirtualStorageService.aidl -package com.lody.virtual.server; - - -interface IVirtualStorageService { - - void setVirtualStorage(in String packageName, in int userId, in String vsPath); - - String getVirtualStorage(in String packageName, in int userId); - - void setVirtualStorageState(in String packageName, in int userId, in boolean enable); - - boolean isVirtualStorageEnable(in String packageName, in int userId); - -} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java index 2bd1bf8a9..bf77a3fe3 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/VirtualCore.java @@ -29,7 +29,6 @@ import com.lody.virtual.client.hook.delegate.ComponentDelegate; import com.lody.virtual.client.hook.delegate.PhoneInfoDelegate; import com.lody.virtual.client.hook.delegate.TaskDescriptionDelegate; -import com.lody.virtual.client.ipc.LocalProxyUtils; import com.lody.virtual.client.ipc.ServiceManagerNative; import com.lody.virtual.client.ipc.VActivityManager; import com.lody.virtual.client.ipc.VPackageManager; @@ -42,8 +41,7 @@ import com.lody.virtual.os.VUserHandle; import com.lody.virtual.remote.InstallResult; import com.lody.virtual.remote.InstalledAppInfo; -import com.lody.virtual.server.IAppManager; -import com.lody.virtual.server.IJobScheduler; +import com.lody.virtual.server.interfaces.IAppManager; import com.lody.virtual.server.ServiceCache; import com.lody.virtual.server.interfaces.IAppRequestListener; import com.lody.virtual.server.interfaces.IPackageObserver; @@ -272,11 +270,6 @@ private IAppManager getService() { return singleton.get(); } - private Object getStubInterface() { - return IAppManager.Stub - .asInterface(ServiceManagerNative.getService(ServiceManagerNative.APP)); - } - /** * @return If the current process is used to VA. */ diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java index 6554cb22d..075b779be 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VAccountManager.java @@ -10,14 +10,11 @@ import android.os.Handler; import android.os.RemoteException; -import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.client.stub.AmsTask; -import com.lody.virtual.helper.ipcbus.IPCBus; import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.os.VUserHandle; -import com.lody.virtual.server.IAccountManager; -import com.lody.virtual.server.IActivityManager; +import com.lody.virtual.server.interfaces.IAccountManager; import static com.lody.virtual.helper.compat.AccountManagerCompat.KEY_ANDROID_PACKAGE_NAME; @@ -35,13 +32,13 @@ public static VAccountManager get() { return sMgr; } - public IAccountManager getRemote() { + public IAccountManager getService() { return singleton.get(); } public AuthenticatorDescription[] getAuthenticatorTypes() { try { - return getRemote().getAuthenticatorTypes(VUserHandle.myUserId()); + return getService().getAuthenticatorTypes(VUserHandle.myUserId()); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -49,7 +46,7 @@ public AuthenticatorDescription[] getAuthenticatorTypes() { public void removeAccount(IAccountManagerResponse response, Account account, boolean expectActivityLaunch) { try { - getRemote().removeAccount(VUserHandle.myUserId(), response, account, expectActivityLaunch); + getService().removeAccount(VUserHandle.myUserId(), response, account, expectActivityLaunch); } catch (RemoteException e) { e.printStackTrace(); } @@ -57,7 +54,7 @@ public void removeAccount(IAccountManagerResponse response, Account account, boo public void getAuthToken(IAccountManagerResponse response, Account account, String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch, Bundle loginOptions) { try { - getRemote().getAuthToken(VUserHandle.myUserId(), response, account, authTokenType, notifyOnAuthFailure, expectActivityLaunch, loginOptions); + getService().getAuthToken(VUserHandle.myUserId(), response, account, authTokenType, notifyOnAuthFailure, expectActivityLaunch, loginOptions); } catch (RemoteException e) { e.printStackTrace(); } @@ -65,7 +62,7 @@ public void getAuthToken(IAccountManagerResponse response, Account account, Stri public boolean addAccountExplicitly(Account account, String password, Bundle extras) { try { - return getRemote().addAccountExplicitly(VUserHandle.myUserId(), account, password, extras); + return getService().addAccountExplicitly(VUserHandle.myUserId(), account, password, extras); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -73,7 +70,7 @@ public boolean addAccountExplicitly(Account account, String password, Bundle ext public Account[] getAccounts(int userId, String type) { try { - return getRemote().getAccounts(userId, type); + return getService().getAccounts(userId, type); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -81,7 +78,7 @@ public Account[] getAccounts(int userId, String type) { public Account[] getAccounts(String type) { try { - return getRemote().getAccounts(VUserHandle.myUserId(), type); + return getService().getAccounts(VUserHandle.myUserId(), type); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -89,7 +86,7 @@ public Account[] getAccounts(String type) { public String peekAuthToken(Account account, String authTokenType) { try { - return getRemote().peekAuthToken(VUserHandle.myUserId(), account, authTokenType); + return getService().peekAuthToken(VUserHandle.myUserId(), account, authTokenType); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -97,7 +94,7 @@ public String peekAuthToken(Account account, String authTokenType) { public String getPreviousName(Account account) { try { - return getRemote().getPreviousName(VUserHandle.myUserId(), account); + return getService().getPreviousName(VUserHandle.myUserId(), account); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -105,7 +102,7 @@ public String getPreviousName(Account account) { public void hasFeatures(IAccountManagerResponse response, Account account, String[] features) { try { - getRemote().hasFeatures(VUserHandle.myUserId(), response, account, features); + getService().hasFeatures(VUserHandle.myUserId(), response, account, features); } catch (RemoteException e) { e.printStackTrace(); } @@ -113,7 +110,7 @@ public void hasFeatures(IAccountManagerResponse response, Account account, Strin public boolean accountAuthenticated(Account account) { try { - return getRemote().accountAuthenticated(VUserHandle.myUserId(), account); + return getService().accountAuthenticated(VUserHandle.myUserId(), account); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -121,7 +118,7 @@ public boolean accountAuthenticated(Account account) { public void clearPassword(Account account) { try { - getRemote().clearPassword(VUserHandle.myUserId(), account); + getService().clearPassword(VUserHandle.myUserId(), account); } catch (RemoteException e) { e.printStackTrace(); } @@ -129,7 +126,7 @@ public void clearPassword(Account account) { public void renameAccount(IAccountManagerResponse response, Account accountToRename, String newName) { try { - getRemote().renameAccount(VUserHandle.myUserId(), response, accountToRename, newName); + getService().renameAccount(VUserHandle.myUserId(), response, accountToRename, newName); } catch (RemoteException e) { e.printStackTrace(); } @@ -137,7 +134,7 @@ public void renameAccount(IAccountManagerResponse response, Account accountToRen public void setPassword(Account account, String password) { try { - getRemote().setPassword(VUserHandle.myUserId(), account, password); + getService().setPassword(VUserHandle.myUserId(), account, password); } catch (RemoteException e) { e.printStackTrace(); } @@ -145,7 +142,7 @@ public void setPassword(Account account, String password) { public void addAccount(int userId, IAccountManagerResponse response, String accountType, String authTokenType, String[] requiredFeatures, boolean expectActivityLaunch, Bundle optionsIn) { try { - getRemote().addAccount(userId, response, accountType, authTokenType, requiredFeatures, expectActivityLaunch, optionsIn); + getService().addAccount(userId, response, accountType, authTokenType, requiredFeatures, expectActivityLaunch, optionsIn); } catch (RemoteException e) { e.printStackTrace(); } @@ -153,7 +150,7 @@ public void addAccount(int userId, IAccountManagerResponse response, String acco public void addAccount(IAccountManagerResponse response, String accountType, String authTokenType, String[] requiredFeatures, boolean expectActivityLaunch, Bundle optionsIn) { try { - getRemote().addAccount(VUserHandle.myUserId(), response, accountType, authTokenType, requiredFeatures, expectActivityLaunch, optionsIn); + getService().addAccount(VUserHandle.myUserId(), response, accountType, authTokenType, requiredFeatures, expectActivityLaunch, optionsIn); } catch (RemoteException e) { e.printStackTrace(); } @@ -161,7 +158,7 @@ public void addAccount(IAccountManagerResponse response, String accountType, Str public void updateCredentials(IAccountManagerResponse response, Account account, String authTokenType, boolean expectActivityLaunch, Bundle loginOptions) { try { - getRemote().updateCredentials(VUserHandle.myUserId(), response, account, authTokenType, expectActivityLaunch, loginOptions); + getService().updateCredentials(VUserHandle.myUserId(), response, account, authTokenType, expectActivityLaunch, loginOptions); } catch (RemoteException e) { e.printStackTrace(); } @@ -169,7 +166,7 @@ public void updateCredentials(IAccountManagerResponse response, Account account, public boolean removeAccountExplicitly(Account account) { try { - return getRemote().removeAccountExplicitly(VUserHandle.myUserId(), account); + return getService().removeAccountExplicitly(VUserHandle.myUserId(), account); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -177,7 +174,7 @@ public boolean removeAccountExplicitly(Account account) { public void setUserData(Account account, String key, String value) { try { - getRemote().setUserData(VUserHandle.myUserId(), account, key, value); + getService().setUserData(VUserHandle.myUserId(), account, key, value); } catch (RemoteException e) { e.printStackTrace(); } @@ -185,7 +182,7 @@ public void setUserData(Account account, String key, String value) { public void editProperties(IAccountManagerResponse response, String accountType, boolean expectActivityLaunch) { try { - getRemote().editProperties(VUserHandle.myUserId(), response, accountType, expectActivityLaunch); + getService().editProperties(VUserHandle.myUserId(), response, accountType, expectActivityLaunch); } catch (RemoteException e) { e.printStackTrace(); } @@ -193,7 +190,7 @@ public void editProperties(IAccountManagerResponse response, String accountType, public void getAuthTokenLabel(IAccountManagerResponse response, String accountType, String authTokenType) { try { - getRemote().getAuthTokenLabel(VUserHandle.myUserId(), response, accountType, authTokenType); + getService().getAuthTokenLabel(VUserHandle.myUserId(), response, accountType, authTokenType); } catch (RemoteException e) { e.printStackTrace(); } @@ -201,7 +198,7 @@ public void getAuthTokenLabel(IAccountManagerResponse response, String accountTy public void confirmCredentials(IAccountManagerResponse response, Account account, Bundle options, boolean expectActivityLaunch) { try { - getRemote().confirmCredentials(VUserHandle.myUserId(), response, account, options, expectActivityLaunch); + getService().confirmCredentials(VUserHandle.myUserId(), response, account, options, expectActivityLaunch); } catch (RemoteException e) { e.printStackTrace(); } @@ -209,7 +206,7 @@ public void confirmCredentials(IAccountManagerResponse response, Account account public void invalidateAuthToken(String accountType, String authToken) { try { - getRemote().invalidateAuthToken(VUserHandle.myUserId(), accountType, authToken); + getService().invalidateAuthToken(VUserHandle.myUserId(), accountType, authToken); } catch (RemoteException e) { e.printStackTrace(); } @@ -217,7 +214,7 @@ public void invalidateAuthToken(String accountType, String authToken) { public void getAccountsByFeatures(IAccountManagerResponse response, String type, String[] features) { try { - getRemote().getAccountsByFeatures(VUserHandle.myUserId(), response, type, features); + getService().getAccountsByFeatures(VUserHandle.myUserId(), response, type, features); } catch (RemoteException e) { e.printStackTrace(); } @@ -225,7 +222,7 @@ public void getAccountsByFeatures(IAccountManagerResponse response, String type, public void setAuthToken(Account account, String authTokenType, String authToken) { try { - getRemote().setAuthToken(VUserHandle.myUserId(), account, authTokenType, authToken); + getService().setAuthToken(VUserHandle.myUserId(), account, authTokenType, authToken); } catch (RemoteException e) { e.printStackTrace(); } @@ -233,7 +230,7 @@ public void setAuthToken(Account account, String authTokenType, String authToken public Object getPassword(Account account) { try { - return getRemote().getPassword(VUserHandle.myUserId(), account); + return getService().getPassword(VUserHandle.myUserId(), account); } catch (RemoteException e) { return VirtualRuntime.crash(e); } @@ -241,7 +238,7 @@ public Object getPassword(Account account) { public String getUserData(Account account, String key) { try { - return getRemote().getUserData(VUserHandle.myUserId(), account, key); + return getService().getUserData(VUserHandle.myUserId(), account, key); } catch (RemoteException e) { return VirtualRuntime.crash(e); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java index b796a82be..b4a7a537b 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VActivityManager.java @@ -18,7 +18,6 @@ import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.client.hook.secondary.ServiceConnectionDelegate; import com.lody.virtual.helper.compat.ActivityManagerCompat; -import com.lody.virtual.helper.ipcbus.IPCBus; import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.helper.utils.ComponentUtils; import com.lody.virtual.os.VUserHandle; @@ -27,8 +26,7 @@ import com.lody.virtual.remote.PendingIntentData; import com.lody.virtual.remote.PendingResultData; import com.lody.virtual.remote.VParceledListSlice; -import com.lody.virtual.server.IActivityManager; -import com.lody.virtual.server.interfaces.IProcessObserver; +import com.lody.virtual.server.interfaces.IActivityManager; import java.util.HashMap; import java.util.List; @@ -55,12 +53,6 @@ public IActivityManager getService() { } - private Object getRemoteInterface() { - return IActivityManager.Stub - .asInterface(ServiceManagerNative.getService(ServiceManagerNative.ACTIVITY)); - } - - public int startActivity(Intent intent, ActivityInfo info, IBinder resultTo, Bundle options, String resultWho, int requestCode, int userId) { try { return getService().startActivity(intent, info, resultTo, options, resultWho, requestCode, userId); @@ -326,14 +318,6 @@ public void killApplicationProcess(String procName, int uid) { } } - public void registerProcessObserver(IProcessObserver observer) { - try { - getService().registerProcessObserver(observer); - } catch (RemoteException e) { - e.printStackTrace(); - } - } - public void killAppByPkg(String pkg, int userId) { try { getService().killAppByPkg(pkg, userId); @@ -342,14 +326,6 @@ public void killAppByPkg(String pkg, int userId) { } } - public void unregisterProcessObserver(IProcessObserver observer) { - try { - getService().unregisterProcessObserver(observer); - } catch (RemoteException e) { - e.printStackTrace(); - } - } - public void appDoneExecuting() { try { getService().appDoneExecuting(); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java index e8654f92b..4bd0cb06e 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VDeviceManager.java @@ -5,7 +5,7 @@ import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.remote.VDeviceInfo; -import com.lody.virtual.server.IDeviceInfoManager; +import com.lody.virtual.server.interfaces.IDeviceInfoManager; /** * @author Lody diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java index c22bd7f69..a0b0de9e0 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java @@ -5,7 +5,7 @@ import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.helper.ipcbus.IPCSingleton; -import com.lody.virtual.server.IJobScheduler; +import com.lody.virtual.server.interfaces.IJobService; import java.util.List; @@ -17,13 +17,13 @@ public class VJobScheduler { private static final VJobScheduler sInstance = new VJobScheduler(); - private IPCSingleton singleton = new IPCSingleton<>(IJobScheduler.class); + private IPCSingleton singleton = new IPCSingleton<>(IJobService.class); public static VJobScheduler get() { return sInstance; } - public IJobScheduler getService() { + public IJobService getService() { return singleton.get(); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java index 653044d77..19cfb61b1 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VNotificationManager.java @@ -1,13 +1,11 @@ package com.lody.virtual.client.ipc; import android.app.Notification; -import android.os.IBinder; import android.os.RemoteException; import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.helper.ipcbus.IPCSingleton; -import com.lody.virtual.server.IJobScheduler; -import com.lody.virtual.server.INotificationManager; +import com.lody.virtual.server.interfaces.INotificationManager; import com.lody.virtual.server.notification.NotificationCompat; /** @@ -31,7 +29,7 @@ public INotificationManager getService() { } public boolean dealNotification(int id, Notification notification, String packageName) { - if(notification == null)return false; + if (notification == null) return false; return VirtualCore.get().getHostPkg().equals(packageName) || mNotificationCompat.dealNotification(id, notification, packageName); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java index d3e0ad136..2bff2d514 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VPackageManager.java @@ -10,13 +10,12 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.os.IBinder; import android.os.RemoteException; import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.server.IPackageInstaller; -import com.lody.virtual.server.IPackageManager; +import com.lody.virtual.server.interfaces.IPackageManager; import java.util.List; @@ -33,12 +32,7 @@ public static VPackageManager get() { } public IPackageManager getService() { - return singleton.get(); - } - - private Object getRemoteInterface() { - final IBinder pmBinder = ServiceManagerNative.getService(ServiceManagerNative.PACKAGE); - return IPackageManager.Stub.asInterface(pmBinder); + return singleton.get(); } public int checkPermission(String permName, String pkgName, int userId) { @@ -254,7 +248,7 @@ public String getNameForUid(int uid) { public IPackageInstaller getPackageInstaller() { try { - return getService().getPackageInstaller(); + return IPackageInstaller.Stub.asInterface(getService().getPackageInstaller()); } catch (RemoteException e) { return VirtualRuntime.crash(e); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java index 284d96057..98160ffce 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualLocationManager.java @@ -7,7 +7,7 @@ import com.lody.virtual.helper.ipcbus.IPCSingleton; import com.lody.virtual.remote.vloc.VCell; import com.lody.virtual.remote.vloc.VLocation; -import com.lody.virtual.server.IVirtualLocationManager; +import com.lody.virtual.server.interfaces.IVirtualLocationManager; import java.util.List; diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java index c5389b686..81d7b6b1e 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VirtualStorageManager.java @@ -5,7 +5,7 @@ import com.lody.virtual.client.env.VirtualRuntime; import com.lody.virtual.helper.ipcbus.IPCSingleton; -import com.lody.virtual.server.IVirtualStorageService; +import com.lody.virtual.server.interfaces.IVirtualStorageService; /** * @author Lody diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java index 4fb65cb57..aa066b410 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCBus.java @@ -37,6 +37,6 @@ public static T get(Class interfaceClass) { return null; } //noinspection unchecked - return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new IPCTranslator(serverInterface, binder)); + return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new IPCInvocationBridge(serverInterface, binder)); } } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCTranslator.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCInvocationBridge.java similarity index 83% rename from VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCTranslator.java rename to VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCInvocationBridge.java index 4121ccc65..cff24a10f 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCTranslator.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCInvocationBridge.java @@ -8,12 +8,12 @@ /** * @author Lody */ -public class IPCTranslator implements InvocationHandler { +public class IPCInvocationBridge implements InvocationHandler { private ServerInterface serverInterface; private IBinder binder; - public IPCTranslator(ServerInterface serverInterface, IBinder binder) { + public IPCInvocationBridge(ServerInterface serverInterface, IBinder binder) { this.serverInterface = serverInterface; this.binder = binder; } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java index 0c42ef8f6..12ebcde04 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/IPCMethod.java @@ -1,6 +1,8 @@ package com.lody.virtual.helper.ipcbus; +import android.os.Binder; import android.os.IBinder; +import android.os.IInterface; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; @@ -8,6 +10,7 @@ import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; /** * @author Lody @@ -17,13 +20,32 @@ public class IPCMethod { private int code; private Method method; private String interfaceName; + private MethodParamConverter[] converters; + private MethodParamConverter resultConverter; + public IPCMethod(int code, Method method, String interfaceName) { this.code = code; this.method = method; this.interfaceName = interfaceName; + Class[] parameterTypes = method.getParameterTypes(); + converters = new MethodParamConverter[parameterTypes.length]; + for (int i = 0; i < parameterTypes.length; i++) { + if (isAidlParam(parameterTypes[i])) { + converters[i] = new AidlParamConverter(parameterTypes[i]); + } + } + Class returnType = method.getReturnType(); + if (isAidlParam(returnType)) { + resultConverter = new AidlParamConverter(returnType); + } + } + + private boolean isAidlParam(Class type) { + return type.isInterface() && IInterface.class.isAssignableFrom(type); } + public String getInterfaceName() { return interfaceName; } @@ -35,16 +57,44 @@ public Method getMethod() { public void handleTransact(Object server, Parcel data, Parcel reply) { data.enforceInterface(interfaceName); Object[] parameters = data.readArray(getClass().getClassLoader()); - Object res = null; + if (parameters != null && parameters.length > 0) { + for (int i = 0; i < parameters.length; i++) { + if (converters[i] != null) { + parameters[i] = converters[i].convert(parameters[i]); + } + } + } try { - res = method.invoke(server, parameters); + Object res = method.invoke(server, parameters); + reply.writeNoException(); + reply.writeValue(res); } catch (IllegalAccessException e) { e.printStackTrace(); + reply.writeException(e); } catch (InvocationTargetException e) { e.printStackTrace(); + reply.writeException(e); + } + } + + private static Method findAsInterfaceMethod(Class type) { + for (Class innerClass : type.getDeclaredClasses()) { + // public static class Stub extends Binder implements IType + if (Modifier.isStatic(innerClass.getModifiers()) + && Binder.class.isAssignableFrom(innerClass) + && type.isAssignableFrom(innerClass)) { + // public static IType asInterface(android.os.IBinder obj) + for (Method method : innerClass.getDeclaredMethods()) { + if (Modifier.isStatic(method.getModifiers())) { + Class[] types = method.getParameterTypes(); + if (types.length == 1 && types[0] == IBinder.class) { + return method; + } + } + } + } } - reply.writeNoException(); - reply.writeValue(res); + throw new IllegalStateException("Can not found the " + type.getName() + "$Stub.asInterface method."); } public Object callRemote(IBinder server, Object[] args) throws RemoteException { @@ -57,6 +107,9 @@ public Object callRemote(IBinder server, Object[] args) throws RemoteException { server.transact(code, data, reply, 0); reply.readException(); result = readValue(reply); + if (resultConverter != null) { + result = resultConverter.convert(result); + } } finally { data.recycle(); reply.recycle(); @@ -85,4 +138,37 @@ public boolean equals(Object o) { return method != null ? method.equals(ipcMethod.method) : ipcMethod.method == null; } + public interface MethodParamConverter { + Object convert(Object param); + } + + private class AidlParamConverter implements MethodParamConverter { + + private Method asInterfaceMethod; + private Class type; + + AidlParamConverter(Class type) { + this.type = type; + } + + @Override + public Object convert(Object param) { + if (param != null) { + if (asInterfaceMethod == null) { + synchronized (this) { + if (asInterfaceMethod == null) { + asInterfaceMethod = findAsInterfaceMethod(type); + } + } + } + try { + return asInterfaceMethod.invoke(null, param); + } catch (Throwable e) { + throw new IllegalStateException(e); + } + } + return null; + } + } + } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java index 68444c578..459b786a6 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/ipcbus/TransformBinder.java @@ -26,7 +26,11 @@ protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) thr } IPCMethod method = serverInterface.getIPCMethod(code); if (method != null) { - method.handleTransact(server, data, reply); + try { + method.handleTransact(server, data, reply); + } catch (Throwable e) { + e.printStackTrace(); + } return true; } return super.onTransact(code, data, reply, flags); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java index fbf04fd92..20b6e4537 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/os/VUserManager.java @@ -4,14 +4,11 @@ import android.os.RemoteException; import android.util.Log; -import com.lody.virtual.client.ipc.ServiceManagerNative; import com.lody.virtual.helper.ipcbus.IPCBus; -import com.lody.virtual.server.IUserManager; +import com.lody.virtual.server.interfaces.IUserManager; import java.util.List; -import static com.lody.virtual.client.ipc.ServiceManagerNative.USER; - /** * Manages users and user details on a multi-user system. */ diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java index 16b446a43..a3bd51306 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java @@ -11,7 +11,6 @@ import android.os.RemoteException; import com.lody.virtual.client.core.VirtualCore; -import com.lody.virtual.client.ipc.ServiceManagerNative; import com.lody.virtual.client.stub.DaemonService; import com.lody.virtual.helper.compat.BundleCompat; import com.lody.virtual.helper.ipcbus.IPCBus; @@ -19,7 +18,16 @@ import com.lody.virtual.server.am.BroadcastSystem; import com.lody.virtual.server.am.VActivityManagerService; import com.lody.virtual.server.device.VDeviceManagerService; +import com.lody.virtual.server.interfaces.IAccountManager; +import com.lody.virtual.server.interfaces.IActivityManager; +import com.lody.virtual.server.interfaces.IAppManager; +import com.lody.virtual.server.interfaces.IDeviceInfoManager; +import com.lody.virtual.server.interfaces.INotificationManager; +import com.lody.virtual.server.interfaces.IPackageManager; import com.lody.virtual.server.interfaces.IServiceFetcher; +import com.lody.virtual.server.interfaces.IUserManager; +import com.lody.virtual.server.interfaces.IVirtualLocationManager; +import com.lody.virtual.server.interfaces.IVirtualStorageService; import com.lody.virtual.server.job.VJobSchedulerService; import com.lody.virtual.server.location.VirtualLocationService; import com.lody.virtual.server.notification.VNotificationManagerService; @@ -28,6 +36,8 @@ import com.lody.virtual.server.pm.VUserManagerService; import com.lody.virtual.server.vs.VirtualStorageService; +import mirror.android.app.job.IJobScheduler; + /** * @author Lody */ diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/accounts/VAccountManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/accounts/VAccountManagerService.java index fb37458fb..db74c4ff9 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/accounts/VAccountManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/accounts/VAccountManagerService.java @@ -34,8 +34,8 @@ import com.lody.virtual.os.VBinder; import com.lody.virtual.os.VEnvironment; import com.lody.virtual.os.VUserHandle; -import com.lody.virtual.server.IAccountManager; import com.lody.virtual.server.am.VActivityManagerService; +import com.lody.virtual.server.interfaces.IAccountManager; import com.lody.virtual.server.pm.VPackageManagerService; import org.xmlpull.v1.XmlPullParser; @@ -62,7 +62,7 @@ /** * @author Lody */ -public class VAccountManagerService extends IAccountManager.Stub { +public class VAccountManagerService implements IAccountManager { private static final AtomicReference sInstance = new AtomicReference<>(); private static final long CHECK_IN_TIME = 30 * 24 * 60 * 1000L; @@ -185,16 +185,6 @@ private List getAccountList(int userId, String type) { } } - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { - try { - return super.onTransact(code, data, reply, flags); - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } - } - @Override public final void getAuthToken(final int userId, final IAccountManagerResponse response, final Account account, final String authTokenType, final boolean notifyOnAuthFailure, boolean expectActivityLaunch, final Bundle loginOptions) { if (response == null) { diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/VActivityManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/VActivityManagerService.java index a034a5649..e6f720835 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/VActivityManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/VActivityManagerService.java @@ -49,7 +49,7 @@ import com.lody.virtual.remote.PendingIntentData; import com.lody.virtual.remote.PendingResultData; import com.lody.virtual.remote.VParceledListSlice; -import com.lody.virtual.server.IActivityManager; +import com.lody.virtual.server.interfaces.IActivityManager; import com.lody.virtual.server.interfaces.IProcessObserver; import com.lody.virtual.server.pm.PackageCacheManager; import com.lody.virtual.server.pm.PackageSetting; @@ -68,12 +68,13 @@ import mirror.android.app.IServiceConnectionO; import static android.os.Process.killProcess; +import static com.lody.virtual.os.VBinder.getCallingPid; import static com.lody.virtual.os.VUserHandle.getUserId; /** * @author Lody */ -public class VActivityManagerService extends IActivityManager.Stub { +public class VActivityManagerService implements IActivityManager { private static final boolean BROADCAST_NOT_STARTED_PKG = false; @@ -233,7 +234,7 @@ private void processDead(ProcessRecord record) { public IBinder acquireProviderClient(int userId, ProviderInfo info) { ProcessRecord callerApp; synchronized (mPidsSelfLocked) { - callerApp = findProcessLocked(VBinder.getCallingPid()); + callerApp = findProcessLocked(getCallingPid()); } if (callerApp == null) { throw new SecurityException("Who are you?"); @@ -263,17 +264,6 @@ public String getCallingPackage(int userId, IBinder token) { return mMainStack.getCallingPackage(userId, token); } - - @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { - try { - return super.onTransact(code, data, reply, flags); - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } - } - private void addRecord(ServiceRecord r) { mHistory.add(r); } @@ -389,7 +379,7 @@ private void stopServiceCommon(ServiceRecord r, ComponentName className) { // Report to all of the connections that the service is no longer // available. try { - if(Build.VERSION.SDK_INT >= 26) { + if (Build.VERSION.SDK_INT >= 26) { IServiceConnectionO.connected.call(connection, className, null, true); } else { connection.connected(className, null); @@ -560,7 +550,7 @@ public void publishService(IBinder token, Intent intent, IBinder service, int us } } - private void connectService(IServiceConnection conn, ComponentName component, ServiceRecord.IntentBindRecord r,boolean dead) { + private void connectService(IServiceConnection conn, ComponentName component, ServiceRecord.IntentBindRecord r, boolean dead) { try { BinderDelegateService delegateService = new BinderDelegateService(component, r.binder); if (Build.VERSION.SDK_INT >= 26) { @@ -718,7 +708,7 @@ private void attachClient(int pid, final IBinder clientBinder) { } try { final ProcessRecord record = app; - clientBinder.linkToDeath(new DeathRecipient() { + clientBinder.linkToDeath(new IBinder.DeathRecipient() { @Override public void binderDied() { clientBinder.unlinkToDeath(this, 0); @@ -941,16 +931,6 @@ public void dump() { } - @Override - public void registerProcessObserver(IProcessObserver observer) { - - } - - @Override - public void unregisterProcessObserver(IProcessObserver observer) { - - } - @Override public String getInitialPackage(int pid) { synchronized (mPidsSelfLocked) { @@ -970,7 +950,7 @@ public void handleApplicationCrash() { @Override public void appDoneExecuting() { synchronized (mPidsSelfLocked) { - ProcessRecord r = mPidsSelfLocked.get(VBinder.getCallingPid()); + ProcessRecord r = mPidsSelfLocked.get(getCallingPid()); if (r != null) { r.doneExecuting = true; r.lock.open(); @@ -1118,7 +1098,7 @@ public void broadcastFinish(PendingResultData res) { } @Override - public void notifyBadgerChange(BadgerInfo info) throws RemoteException { + public void notifyBadgerChange(BadgerInfo info) { Intent intent = new Intent(VASettings.ACTION_BADGER_CHANGE); intent.putExtra("userId", info.userId); intent.putExtra("packageName", info.packageName); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/device/VDeviceManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/device/VDeviceManagerService.java index 326fa8bee..8064737fb 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/device/VDeviceManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/device/VDeviceManagerService.java @@ -6,7 +6,7 @@ import com.lody.virtual.helper.collection.SparseArray; import com.lody.virtual.remote.VDeviceInfo; -import com.lody.virtual.server.IDeviceInfoManager; +import com.lody.virtual.server.interfaces.IDeviceInfoManager; import java.util.ArrayList; import java.util.Collections; @@ -17,7 +17,7 @@ * @author Lody */ -public class VDeviceManagerService extends IDeviceInfoManager.Stub { +public class VDeviceManagerService implements IDeviceInfoManager { private static VDeviceManagerService sInstance = new VDeviceManagerService(); private final SparseArray mDeviceInfos = new SparseArray<>(); @@ -53,7 +53,7 @@ private void addDeviceInfoToPool(VDeviceInfo info) { } @Override - public VDeviceInfo getDeviceInfo(int userId) throws RemoteException { + public VDeviceInfo getDeviceInfo(int userId) { VDeviceInfo info; synchronized (mDeviceInfos) { info = mDeviceInfos.get(userId); @@ -67,7 +67,7 @@ public VDeviceInfo getDeviceInfo(int userId) throws RemoteException { } @Override - public void updateDeviceInfo(int userId, VDeviceInfo info) throws RemoteException { + public void updateDeviceInfo(int userId, VDeviceInfo info) { synchronized (mDeviceInfos) { if (info != null) { mDeviceInfos.put(userId, info); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAccountManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAccountManager.java new file mode 100644 index 000000000..6a2d85871 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAccountManager.java @@ -0,0 +1,61 @@ +package com.lody.virtual.server.interfaces; + +import android.accounts.Account; +import android.accounts.AuthenticatorDescription; +import android.accounts.IAccountManagerResponse; +import android.os.Bundle; +import android.os.RemoteException; + +/** + * @author Lody + */ +public interface IAccountManager { + + AuthenticatorDescription[] getAuthenticatorTypes(int userId) throws RemoteException; + + void getAccountsByFeatures(int userId, IAccountManagerResponse response, String type, String[] features) throws RemoteException; + + String getPreviousName(int userId, Account account) throws RemoteException; + + Account[] getAccounts(int userId, String type) throws RemoteException; + + void getAuthToken(int userId, IAccountManagerResponse response, Account account, String authTokenType, boolean notifyOnAuthFailure, boolean expectActivityLaunch, Bundle loginOptions) throws RemoteException; + + void setPassword(int userId, Account account, String password) throws RemoteException; + + void setAuthToken(int userId, Account account, String authTokenType, String authToken) throws RemoteException; + + void setUserData(int userId, Account account, String key, String value) throws RemoteException; + + void hasFeatures(int userId, IAccountManagerResponse response, Account account, String[] features) throws RemoteException; + + void updateCredentials(int userId, IAccountManagerResponse response, Account account, String authTokenType, boolean expectActivityLaunch, Bundle loginOptions) throws RemoteException; + + void editProperties(int userId, IAccountManagerResponse response, String accountType, boolean expectActivityLaunch) throws RemoteException; + + void getAuthTokenLabel(int userId, IAccountManagerResponse response, String accountType, String authTokenType) throws RemoteException; + + String getUserData(int userId, Account account, String key) throws RemoteException; + + String getPassword(int userId, Account account) throws RemoteException; + + void confirmCredentials(int userId, IAccountManagerResponse response, Account account, Bundle options, boolean expectActivityLaunch) throws RemoteException; + + void addAccount(int userId, IAccountManagerResponse response, String accountType, String authTokenType, String[] requiredFeatures, boolean expectActivityLaunch, Bundle optionsIn) throws RemoteException; + + boolean addAccountExplicitly(int userId, Account account, String password, Bundle extras) throws RemoteException; + + boolean removeAccountExplicitly(int userId, Account account) throws RemoteException; + + void renameAccount(int userId, IAccountManagerResponse response, Account accountToRename, String newName) throws RemoteException; + + void removeAccount(int userId, IAccountManagerResponse response, Account account, boolean expectActivityLaunch) throws RemoteException; + + void clearPassword(int userId, Account account) throws RemoteException; + + boolean accountAuthenticated(int userId, Account account) throws RemoteException; + + void invalidateAuthToken(int userId, String accountType, String authToken) throws RemoteException; + + String peekAuthToken(int userId, Account account, String authTokenType) throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IActivityManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IActivityManager.java new file mode 100644 index 000000000..408b06add --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IActivityManager.java @@ -0,0 +1,106 @@ +package com.lody.virtual.server.interfaces; + +import android.app.*; +import android.content.*; +import android.content.pm.*; +import android.os.*; + +import com.lody.virtual.remote.*; + +/** + * @author Lody + */ +public interface IActivityManager { + + int initProcess(String packageName, String processName, int userId) throws RemoteException; + + int getFreeStubCount() throws RemoteException; + + int getSystemPid() throws RemoteException; + + int getUidByPid(int pid) throws RemoteException; + + boolean isAppProcess(String processName) throws RemoteException; + + boolean isAppRunning(String packageName, int userId) throws RemoteException; + + boolean isAppPid(int pid) throws RemoteException; + + String getAppProcessName(int pid) throws RemoteException; + + java.util.List getProcessPkgList(int pid) throws RemoteException; + + void killAllApps() throws RemoteException; + + void killAppByPkg(String pkg, int userId) throws RemoteException; + + void killApplicationProcess(String processName, int vuid) throws RemoteException; + + void dump() throws RemoteException; + + String getInitialPackage(int pid) throws RemoteException; + + void handleApplicationCrash() throws RemoteException; + + void appDoneExecuting() throws RemoteException; + + int startActivities(Intent[] intents, String[] resolvedTypes, IBinder token, Bundle options, int userId) throws RemoteException; + + int startActivity(Intent intent, ActivityInfo info, IBinder resultTo, Bundle options, String resultWho, int requestCode, int userId) throws RemoteException; + + void onActivityCreated(ComponentName component, ComponentName caller, IBinder token, Intent intent, String affinity, int taskId, int launchMode, int flags) throws RemoteException; + + void onActivityResumed(int userId, IBinder token) throws RemoteException; + + boolean onActivityDestroyed(int userId, IBinder token) throws RemoteException; + + ComponentName getActivityClassForToken(int userId, IBinder token) throws RemoteException; + + String getCallingPackage(int userId, IBinder token) throws RemoteException; + + ComponentName getCallingActivity(int userId, IBinder token) throws RemoteException; + + AppTaskInfo getTaskInfo(int taskId) throws RemoteException; + + String getPackageForToken(int userId, IBinder token) throws RemoteException; + + boolean isVAServiceToken(IBinder token) throws RemoteException; + + ComponentName startService(IBinder caller, Intent service, String resolvedType, int userId) throws RemoteException; + + int stopService(IBinder caller, Intent service, String resolvedType, int userId) throws RemoteException; + + boolean stopServiceToken(ComponentName className, IBinder token, int startId, int userId) throws RemoteException; + + void setServiceForeground(ComponentName className, IBinder token, int id, Notification notification, boolean removeNotification, int userId) throws RemoteException; + + int bindService(IBinder caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) throws RemoteException; + + boolean unbindService(IServiceConnection connection, int userId) throws RemoteException; + + void unbindFinished(IBinder token, Intent service, boolean doRebind, int userId) throws RemoteException; + + void serviceDoneExecuting(IBinder token, int type, int startId, int res, int userId) throws RemoteException; + + IBinder peekService(Intent service, String resolvedType, int userId) throws RemoteException; + + void publishService(IBinder token, Intent intent, IBinder service, int userId) throws RemoteException; + + VParceledListSlice getServices(int maxNum, int flags, int userId) throws RemoteException; + + IBinder acquireProviderClient(int userId, ProviderInfo info) throws RemoteException; + + PendingIntentData getPendingIntent(IBinder binder) throws RemoteException; + + void addPendingIntent(IBinder binder, String packageName) throws RemoteException; + + void removePendingIntent(IBinder binder) throws RemoteException; + + String getPackageForIntentSender(IBinder binder) throws RemoteException; + + void processRestarted(String packageName, String processName, int userId) throws RemoteException; + + void broadcastFinish(PendingResultData res) throws RemoteException; + + void notifyBadgerChange(BadgerInfo info) throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAppManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAppManager.java new file mode 100644 index 000000000..cbf2e085f --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IAppManager.java @@ -0,0 +1,58 @@ +package com.lody.virtual.server.interfaces; + +import android.os.RemoteException; + +import com.lody.virtual.remote.InstallResult; +import com.lody.virtual.remote.InstalledAppInfo; + +import java.util.List; + +/** + * @author Lody + */ +public interface IAppManager { + + int[] getPackageInstalledUsers(String packageName) throws RemoteException; + + void scanApps() throws RemoteException; + + void addVisibleOutsidePackage(String pkg) throws RemoteException; + + void removeVisibleOutsidePackage(String pkg) throws RemoteException; + + boolean isOutsidePackageVisible(String pkg) throws RemoteException; + + InstalledAppInfo getInstalledAppInfo(String pkg, int flags) throws RemoteException; + + InstallResult installPackage(String path, int flags) throws RemoteException; + + boolean isPackageLaunched(int userId, String packageName) throws RemoteException; + + void setPackageHidden(int userId, String packageName, boolean hidden) throws RemoteException; + + boolean installPackageAsUser(int userId, String packageName) throws RemoteException; + + boolean uninstallPackageAsUser(String packageName, int userId) throws RemoteException; + + boolean uninstallPackage(String packageName) throws RemoteException; + + List getInstalledApps(int flags) throws RemoteException; + + List getInstalledAppsAsUser(int userId, int flags) throws RemoteException; + + int getInstalledAppCount() throws RemoteException; + + boolean isAppInstalled(String packageName) throws RemoteException; + + boolean isAppInstalledAsUser(int userId, String packageName) throws RemoteException; + + void registerObserver(IPackageObserver observer) throws RemoteException; + + void unregisterObserver(IPackageObserver observer) throws RemoteException; + + void setAppRequestListener(IAppRequestListener listener) throws RemoteException; + + void clearAppRequestListener() throws RemoteException; + + IAppRequestListener getAppRequestListener() throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IDeviceInfoManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IDeviceInfoManager.java new file mode 100644 index 000000000..c7470892d --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IDeviceInfoManager.java @@ -0,0 +1,16 @@ +package com.lody.virtual.server.interfaces; + +import android.os.RemoteException; + +import com.lody.virtual.remote.VDeviceInfo; + +/** + * @author Lody + */ +public interface IDeviceInfoManager { + + VDeviceInfo getDeviceInfo(int userId) throws RemoteException; + + void updateDeviceInfo(int userId, VDeviceInfo info) throws RemoteException; + +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java new file mode 100644 index 000000000..36c08a5bc --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java @@ -0,0 +1,20 @@ +package com.lody.virtual.server.interfaces; + +import android.app.job.JobInfo; +import android.os.RemoteException; + +import java.util.List; + +/** + * @author Lody + */ +public interface IJobService { + + int schedule(JobInfo job) throws RemoteException; + + void cancel(int jobId) throws RemoteException; + + void cancelAll() throws RemoteException; + + List getAllPendingJobs() throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/INotificationManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/INotificationManager.java new file mode 100644 index 000000000..9bc7d41c4 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/INotificationManager.java @@ -0,0 +1,21 @@ +package com.lody.virtual.server.interfaces; + +import android.os.RemoteException; + +/** + * @author Lody + */ +public interface INotificationManager { + + int dealNotificationId(int id, String packageName, String tag, int userId) throws RemoteException; + + String dealNotificationTag(int id, String packageName, String tag, int userId) throws RemoteException; + + boolean areNotificationsEnabledForPackage(String packageName, int userId) throws RemoteException; + + void setNotificationsEnabledForPackage(String packageName, boolean enable, int userId) throws RemoteException; + + void addNotification(int id, String tag, String packageName, int userId) throws RemoteException; + + void cancelAllNotification(String packageName, int userId) throws RemoteException; +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IPackageManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IPackageManager.java new file mode 100644 index 000000000..c2e98bd4c --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IPackageManager.java @@ -0,0 +1,72 @@ +package com.lody.virtual.server.interfaces; + +import android.content.*; +import android.content.pm.*; +import android.os.IBinder; +import android.os.RemoteException; + +import com.lody.virtual.remote.VParceledListSlice; + +import java.util.List; + +/** + * @author Lody + */ +public interface IPackageManager { + + int getPackageUid(String packageName, int userId) throws RemoteException; + + String[] getPackagesForUid(int vuid) throws RemoteException; + + List getSharedLibraries(String pkgName) throws RemoteException; + + int checkPermission(String permName, String pkgName, int userId) throws RemoteException; + + PackageInfo getPackageInfo(String packageName, int flags, int userId) throws RemoteException; + + ActivityInfo getActivityInfo(ComponentName componentName, int flags, int userId) throws RemoteException; + + boolean activitySupportsIntent(ComponentName component, Intent intent, String resolvedType) throws RemoteException; + + ActivityInfo getReceiverInfo(ComponentName componentName, int flags, int userId) throws RemoteException; + + ServiceInfo getServiceInfo(ComponentName componentName, int flags, int userId) throws RemoteException; + + ProviderInfo getProviderInfo(ComponentName componentName, int flags, int userId) throws RemoteException; + + ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) throws RemoteException; + + List queryIntentActivities(Intent intent, String resolvedType, int flags, int userId) throws RemoteException; + + List queryIntentReceivers(Intent intent, String resolvedType, int flags, int userId) throws RemoteException; + + ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) throws RemoteException; + + List queryIntentServices(Intent intent, String resolvedType, int flags, int userId) throws RemoteException; + + List queryIntentContentProviders(Intent intent, String resolvedType, int flags, int userId) throws RemoteException; + + VParceledListSlice getInstalledPackages(int flags, int userId) throws RemoteException; + + VParceledListSlice getInstalledApplications(int flags, int userId) throws RemoteException; + + PermissionInfo getPermissionInfo(String name, int flags) throws RemoteException; + + List queryPermissionsByGroup(String group, int flags) throws RemoteException; + + PermissionGroupInfo getPermissionGroupInfo(String name, int flags) throws RemoteException; + + List getAllPermissionGroups(int flags) throws RemoteException; + + ProviderInfo resolveContentProvider(String name, int flags, int userId) throws RemoteException; + + ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) throws RemoteException; + + VParceledListSlice queryContentProviders(String processName, int vuid, int flags) throws RemoteException; + + List querySharedPackages(String packageName) throws RemoteException; + + String getNameForUid(int uid) throws RemoteException; + + IBinder getPackageInstaller() throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IUserManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IUserManager.java new file mode 100644 index 000000000..c3497596a --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IUserManager.java @@ -0,0 +1,37 @@ +package com.lody.virtual.server.interfaces; + +import android.graphics.Bitmap; +import android.os.RemoteException; + +import com.lody.virtual.os.VUserInfo; + +import java.util.List; + +/** + * @author Lody + */ +public interface IUserManager { + VUserInfo createUser(String name, int flags) throws RemoteException; + + boolean removeUser(int userHandle) throws RemoteException; + + void setUserName(int userHandle, String name) throws RemoteException; + + void setUserIcon(int userHandle, Bitmap icon) throws RemoteException; + + Bitmap getUserIcon(int userHandle) throws RemoteException; + + List getUsers(boolean excludeDying) throws RemoteException; + + VUserInfo getUserInfo(int userHandle) throws RemoteException; + + void setGuestEnabled(boolean enable) throws RemoteException; + + boolean isGuestEnabled() throws RemoteException; + + void wipeUser(int userHandle) throws RemoteException; + + int getUserSerialNumber(int userHandle) throws RemoteException; + + int getUserHandle(int userSerialNumber) throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualLocationManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualLocationManager.java new file mode 100644 index 000000000..f7097b5d8 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualLocationManager.java @@ -0,0 +1,44 @@ +package com.lody.virtual.server.interfaces; + +import android.os.RemoteException; + +import com.lody.virtual.remote.vloc.VCell; +import com.lody.virtual.remote.vloc.VLocation; + +import java.util.List; + +/** + * @author Lody + */ +public interface IVirtualLocationManager { + + int getMode(int userId, String pkg) throws RemoteException; + + void setMode(int userId, String pkg, int mode) throws RemoteException; + + void setCell(int userId, String pkg, VCell cell) throws RemoteException; + + void setAllCell(int userId, String pkg, List cell) throws RemoteException; + + void setNeighboringCell(int userId, String pkg, List cell) throws RemoteException; + + void setGlobalCell(VCell cell) throws RemoteException; + + void setGlobalAllCell(List cell) throws RemoteException; + + void setGlobalNeighboringCell(List cell) throws RemoteException; + + VCell getCell(int userId, String pkg) throws RemoteException; + + List getAllCell(int userId, String pkg) throws RemoteException; + + List getNeighboringCell(int userId, String pkg) throws RemoteException; + + void setLocation(int userId, String pkg, VLocation loc) throws RemoteException; + + VLocation getLocation(int userId, String pkg) throws RemoteException; + + void setGlobalLocation(VLocation loc) throws RemoteException; + + VLocation getGlobalLocation() throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualStorageService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualStorageService.java new file mode 100644 index 000000000..a998ad288 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IVirtualStorageService.java @@ -0,0 +1,17 @@ +package com.lody.virtual.server.interfaces; + +import android.os.RemoteException; + +/** + * @author Lody + */ +public interface IVirtualStorageService { + + void setVirtualStorage(String packageName, int userId, String vsPath) throws RemoteException; + + String getVirtualStorage(String packageName, int userId) throws RemoteException; + + void setVirtualStorageState(String packageName, int userId, boolean enable) throws RemoteException; + + boolean isVirtualStorageEnable(String packageName, int userId) throws RemoteException; +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java index b4f0a8f87..7abb6faa2 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java @@ -9,7 +9,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; -import android.os.RemoteException; import android.text.TextUtils; import com.lody.virtual.client.core.VirtualCore; @@ -18,7 +17,7 @@ import com.lody.virtual.helper.utils.Singleton; import com.lody.virtual.os.VBinder; import com.lody.virtual.os.VEnvironment; -import com.lody.virtual.server.IJobScheduler; +import com.lody.virtual.server.interfaces.IJobService; import java.io.File; import java.io.FileInputStream; @@ -34,7 +33,7 @@ * @author Lody */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) -public class VJobSchedulerService extends IJobScheduler.Stub { +public class VJobSchedulerService implements IJobService { private static final String TAG = VJobScheduler.class.getSimpleName(); @@ -179,7 +178,7 @@ public JobConfig[] newArray(int size) { @Override - public int schedule(JobInfo job) throws RemoteException { + public int schedule(JobInfo job) { int vuid = VBinder.getCallingUid(); int id = job.getId(); ComponentName service = job.getService(); @@ -257,7 +256,7 @@ private void readJobs() { } @Override - public void cancel(int jobId) throws RemoteException { + public void cancel(int jobId) { int vuid = VBinder.getCallingUid(); synchronized (mJobStore) { boolean changed = false; @@ -280,7 +279,7 @@ public void cancel(int jobId) throws RemoteException { } @Override - public void cancelAll() throws RemoteException { + public void cancelAll() { int vuid = VBinder.getCallingUid(); synchronized (mJobStore) { boolean changed = false; @@ -303,7 +302,7 @@ public void cancelAll() throws RemoteException { } @Override - public List getAllPendingJobs() throws RemoteException { + public List getAllPendingJobs() { int vuid = VBinder.getCallingUid(); List jobs = mScheduler.getAllPendingJobs(); synchronized (mJobStore) { diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/location/VirtualLocationService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/location/VirtualLocationService.java index dcd387906..e7dedff10 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/location/VirtualLocationService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/location/VirtualLocationService.java @@ -9,7 +9,7 @@ import com.lody.virtual.os.VEnvironment; import com.lody.virtual.remote.vloc.VCell; import com.lody.virtual.remote.vloc.VLocation; -import com.lody.virtual.server.IVirtualLocationManager; +import com.lody.virtual.server.interfaces.IVirtualLocationManager; import java.util.HashMap; import java.util.List; @@ -19,7 +19,7 @@ * @author Lody */ -public class VirtualLocationService extends IVirtualLocationManager.Stub { +public class VirtualLocationService implements IVirtualLocationManager { private static final VirtualLocationService sInstance = new VirtualLocationService(); private final SparseArray> mLocConfigs = new SparseArray<>(); @@ -123,7 +123,7 @@ private VirtualLocationService() { } @Override - public int getMode(int userId, String pkg) throws RemoteException { + public int getMode(int userId, String pkg) { synchronized (mLocConfigs) { VLocConfig config = getOrCreateConfig(userId, pkg); mPersistenceLayer.save(); @@ -132,7 +132,7 @@ public int getMode(int userId, String pkg) throws RemoteException { } @Override - public void setMode(int userId, String pkg, int mode) throws RemoteException { + public void setMode(int userId, String pkg, int mode) { synchronized (mLocConfigs) { getOrCreateConfig(userId, pkg).mode = mode; mPersistenceLayer.save(); @@ -155,43 +155,43 @@ private VLocConfig getOrCreateConfig(int userId, String pkg) { } @Override - public void setCell(int userId, String pkg, VCell cell) throws RemoteException { + public void setCell(int userId, String pkg, VCell cell) { getOrCreateConfig(userId, pkg).cell = cell; mPersistenceLayer.save(); } @Override - public void setAllCell(int userId, String pkg, List cell) throws RemoteException { + public void setAllCell(int userId, String pkg, List cell) { getOrCreateConfig(userId, pkg).allCell = cell; mPersistenceLayer.save(); } @Override - public void setNeighboringCell(int userId, String pkg, List cell) throws RemoteException { + public void setNeighboringCell(int userId, String pkg, List cell) { getOrCreateConfig(userId, pkg).neighboringCell = cell; mPersistenceLayer.save(); } @Override - public void setGlobalCell(VCell cell) throws RemoteException { + public void setGlobalCell(VCell cell) { mGlobalConfig.cell = cell; mPersistenceLayer.save(); } @Override - public void setGlobalAllCell(List cell) throws RemoteException { + public void setGlobalAllCell(List cell) { mGlobalConfig.allCell = cell; mPersistenceLayer.save(); } @Override - public void setGlobalNeighboringCell(List cell) throws RemoteException { + public void setGlobalNeighboringCell(List cell) { mGlobalConfig.neighboringCell = cell; mPersistenceLayer.save(); } @Override - public VCell getCell(int userId, String pkg) throws RemoteException { + public VCell getCell(int userId, String pkg) { VLocConfig config = getOrCreateConfig(userId, pkg); mPersistenceLayer.save(); switch (config.mode) { @@ -206,7 +206,7 @@ public VCell getCell(int userId, String pkg) throws RemoteException { } @Override - public List getAllCell(int userId, String pkg) throws RemoteException { + public List getAllCell(int userId, String pkg) { VLocConfig config = getOrCreateConfig(userId, pkg); mPersistenceLayer.save(); switch (config.mode) { @@ -221,7 +221,7 @@ public List getAllCell(int userId, String pkg) throws RemoteException { } @Override - public List getNeighboringCell(int userId, String pkg) throws RemoteException { + public List getNeighboringCell(int userId, String pkg) { VLocConfig config = getOrCreateConfig(userId, pkg); mPersistenceLayer.save(); switch (config.mode) { @@ -236,13 +236,13 @@ public List getNeighboringCell(int userId, String pkg) throws RemoteExcep } @Override - public void setLocation(int userId, String pkg, VLocation loc) throws RemoteException { + public void setLocation(int userId, String pkg, VLocation loc) { getOrCreateConfig(userId, pkg).location = loc; mPersistenceLayer.save(); } @Override - public VLocation getLocation(int userId, String pkg) throws RemoteException { + public VLocation getLocation(int userId, String pkg) { VLocConfig config = getOrCreateConfig(userId, pkg); mPersistenceLayer.save(); switch (config.mode) { @@ -257,12 +257,12 @@ public VLocation getLocation(int userId, String pkg) throws RemoteException { } @Override - public void setGlobalLocation(VLocation loc) throws RemoteException { + public void setGlobalLocation(VLocation loc) { mGlobalConfig.location = loc; } @Override - public VLocation getGlobalLocation() throws RemoteException { + public VLocation getGlobalLocation() { return mGlobalConfig.location; } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/VNotificationManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/VNotificationManagerService.java index 8ba98af09..a3093b5e2 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/VNotificationManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/notification/VNotificationManagerService.java @@ -5,14 +5,14 @@ import android.text.TextUtils; import com.lody.virtual.helper.utils.VLog; -import com.lody.virtual.server.INotificationManager; +import com.lody.virtual.server.interfaces.INotificationManager; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -public class VNotificationManagerService extends INotificationManager.Stub { +public class VNotificationManagerService implements INotificationManager { private static final AtomicReference gService = new AtomicReference<>(); private NotificationManager mNotificationManager; static final String TAG = NotificationCompat.class.getSimpleName(); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VAppManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VAppManagerService.java index 41c569e37..01541163b 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VAppManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VAppManagerService.java @@ -3,6 +3,7 @@ import android.content.Intent; import android.net.Uri; import android.os.Build; +import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -19,11 +20,11 @@ import com.lody.virtual.os.VUserHandle; import com.lody.virtual.remote.InstallResult; import com.lody.virtual.remote.InstalledAppInfo; -import com.lody.virtual.server.IAppManager; import com.lody.virtual.server.accounts.VAccountManagerService; import com.lody.virtual.server.am.BroadcastSystem; import com.lody.virtual.server.am.UidSystem; import com.lody.virtual.server.am.VActivityManagerService; +import com.lody.virtual.server.interfaces.IAppManager; import com.lody.virtual.server.interfaces.IAppRequestListener; import com.lody.virtual.server.interfaces.IPackageObserver; import com.lody.virtual.server.pm.parser.PackageParserEx; @@ -42,7 +43,7 @@ /** * @author Lody */ -public class VAppManagerService extends IAppManager.Stub { +public class VAppManagerService implements IAppManager { private static final String TAG = VAppManagerService.class.getSimpleName(); private static final AtomicReference sService = new AtomicReference<>(); @@ -513,7 +514,7 @@ public void setAppRequestListener(final IAppRequestListener listener) { this.mAppRequestListener = listener; if (listener != null) { try { - listener.asBinder().linkToDeath(new DeathRecipient() { + listener.asBinder().linkToDeath(new IBinder.DeathRecipient() { @Override public void binderDied() { listener.asBinder().unlinkToDeath(this, 0); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java index 4c5a1f7af..22970a456 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java @@ -13,8 +13,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.Build; -import android.os.Parcel; -import android.os.RemoteException; +import android.os.IBinder; import android.text.TextUtils; import android.util.Log; @@ -25,7 +24,7 @@ import com.lody.virtual.os.VUserHandle; import com.lody.virtual.remote.VParceledListSlice; import com.lody.virtual.server.IPackageInstaller; -import com.lody.virtual.server.IPackageManager; +import com.lody.virtual.server.interfaces.IPackageManager; import com.lody.virtual.server.pm.installer.VPackageInstallerService; import com.lody.virtual.server.pm.parser.PackageParserEx; import com.lody.virtual.server.pm.parser.VPackage; @@ -40,12 +39,11 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicReference; -import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; /** * @author Lody */ -public class VPackageManagerService extends IPackageManager.Stub { +public class VPackageManagerService implements IPackageManager { static final String TAG = "PackageManager"; static final Comparator sResolvePrioritySorter = new Comparator() { @@ -269,7 +267,7 @@ private int updateFlagsNought(int flags) { // give them what they want } else { // Caller expressed no opinion, so match based on user state - flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; + flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; } return flags; } @@ -774,17 +772,7 @@ public List querySharedPackages(String packageName) { } @Override - public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { - try { - return super.onTransact(code, data, reply, flags); - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } - } - - @Override - public IPackageInstaller getPackageInstaller() { + public IBinder getPackageInstaller() { return VPackageInstallerService.get(); } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VUserManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VUserManagerService.java index b45ca62ad..320dc3be1 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VUserManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VUserManagerService.java @@ -25,7 +25,7 @@ import com.lody.virtual.os.VUserInfo; import com.lody.virtual.os.VUserManager; import com.lody.virtual.server.am.VActivityManagerService; -import com.lody.virtual.server.IUserManager; +import com.lody.virtual.server.interfaces.IUserManager; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -47,7 +47,7 @@ /** * @author Lody */ -public class VUserManagerService extends IUserManager.Stub { +public class VUserManagerService implements IUserManager { private static final String LOG_TAG = "VUserManagerService"; @@ -317,7 +317,7 @@ public void makeInitialized(int userId) { if (info == null || info.partial) { VLog.w(LOG_TAG, "makeInitialized: unknown user #" + userId); } - if ((info.flags& VUserInfo.FLAG_INITIALIZED) == 0) { + if ((info.flags & VUserInfo.FLAG_INITIALIZED) == 0) { info.flags |= VUserInfo.FLAG_INITIALIZED; writeUserLocked(info); } @@ -360,6 +360,7 @@ private void writeBitmapLocked(VUserInfo info, Bitmap bitmap) { /** * Returns an array of user ids. This array is cached here for quick access, so do not modify or * cache it elsewhere. + * * @return the array of user ids. */ public int[] getUserIds() { @@ -513,7 +514,7 @@ private void writeUserLocked(VUserInfo userInfo) { serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME, Long.toString(userInfo.lastLoggedInTime)); if (userInfo.iconPath != null) { - serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath); + serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath); } if (userInfo.partial) { serializer.attribute(null, ATTR_PARTIAL, "true"); @@ -699,7 +700,7 @@ public VUserInfo createUser(String name, int flags) { Intent addedIntent = new Intent(Constants.ACTION_USER_ADDED); addedIntent.putExtra(Constants.EXTRA_USER_HANDLE, userInfo.id); VActivityManagerService.get().sendBroadcastAsUser(addedIntent, VUserHandle.ALL, - null); + null); } finally { Binder.restoreCallingIdentity(ident); } @@ -709,6 +710,7 @@ public VUserInfo createUser(String name, int flags) { /** * Removes a user and all data directories created for that user. This method should be called * after the user's processes have been terminated. + * * @param userHandle the user's id */ public boolean removeUser(int userHandle) { @@ -728,15 +730,16 @@ public boolean removeUser(int userHandle) { } if (DBG) VLog.i(LOG_TAG, "Stopping user " + userHandle); int res = VActivityManagerService.get().stopUser(userHandle, - new IStopUserCallback.Stub() { - @Override - public void userStopped(int userId) { - finishRemoveUser(userId); - } - @Override - public void userStopAborted(int userId) { - } - }); + new IStopUserCallback.Stub() { + @Override + public void userStopped(int userId) { + finishRemoveUser(userId); + } + + @Override + public void userStopAborted(int userId) { + } + }); return res == ActivityManagerCompat.USER_OP_SUCCESS; } @@ -749,14 +752,14 @@ void finishRemoveUser(final int userHandle) { Intent addedIntent = new Intent(Constants.ACTION_USER_REMOVED); addedIntent.putExtra(Constants.EXTRA_USER_HANDLE, userHandle); VActivityManagerService.get().sendOrderedBroadcastAsUser(addedIntent, VUserHandle.ALL, - null, + null, new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DBG) { VLog.i(LOG_TAG, "USER_REMOVED broadcast sent, cleaning up user data " - + userHandle); + + userHandle); } new Thread() { public void run() { @@ -843,6 +846,7 @@ private void updateUserIdsLocked() { /** * Make a note of the last started time of a user. + * * @param userId the user that was just foregrounded */ public void userForeground(int userId) { @@ -864,6 +868,7 @@ public void userForeground(int userId) { * Returns the next available user id, filling in any holes in the ids. * TODO: May not be a good idea to recycle ids, in case it results in confusion * for data and battery stats collection, or unexpected cross-talk. + * * @return */ private int getNextAvailableIdLocked() { @@ -880,8 +885,4 @@ private int getNextAvailableIdLocked() { } } - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - - } } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java index 8eedbc776..2e8e04b96 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java @@ -3,7 +3,7 @@ import android.os.RemoteException; import android.util.SparseArray; -import com.lody.virtual.server.IVirtualStorageService; +import com.lody.virtual.server.interfaces.IVirtualStorageService; import com.lody.virtual.server.pm.VUserManagerService; import java.util.HashMap; @@ -12,7 +12,7 @@ * @author Lody */ -public class VirtualStorageService extends IVirtualStorageService.Stub { +public class VirtualStorageService implements IVirtualStorageService { private static final VirtualStorageService sService = new VirtualStorageService(); private final VSPersistenceLayer mLayer = new VSPersistenceLayer(this); @@ -31,7 +31,7 @@ SparseArray> getConfigs() { } @Override - public void setVirtualStorage(String packageName, int userId, String vsPath) throws RemoteException { + public void setVirtualStorage(String packageName, int userId, String vsPath) { checkUserId(userId); synchronized (mConfigs) { VSConfig config = getOrCreateVSConfigLocked(packageName, userId); @@ -57,7 +57,7 @@ private VSConfig getOrCreateVSConfigLocked(String packageName, int userId) { @Override - public String getVirtualStorage(String packageName, int userId) throws RemoteException { + public String getVirtualStorage(String packageName, int userId) { checkUserId(userId); synchronized (mConfigs) { VSConfig config = getOrCreateVSConfigLocked(packageName, userId); @@ -66,7 +66,7 @@ public String getVirtualStorage(String packageName, int userId) throws RemoteExc } @Override - public void setVirtualStorageState(String packageName, int userId, boolean enable) throws RemoteException { + public void setVirtualStorageState(String packageName, int userId, boolean enable) { checkUserId(userId); synchronized (mConfigs) { VSConfig config = getOrCreateVSConfigLocked(packageName, userId); @@ -77,7 +77,7 @@ public void setVirtualStorageState(String packageName, int userId, boolean enabl } @Override - public boolean isVirtualStorageEnable(String packageName, int userId) throws RemoteException { + public boolean isVirtualStorageEnable(String packageName, int userId) { checkUserId(userId); synchronized (mConfigs) { VSConfig config = getOrCreateVSConfigLocked(packageName, userId); From 73e8c826a89c25c61d293df3b2585483fedd23d5 Mon Sep 17 00:00:00 2001 From: "monch.chen@yahoo.com" Date: Tue, 12 Dec 2017 18:15:57 +0800 Subject: [PATCH 021/334] =?UTF-8?q?fix=20=E5=9C=A8=20Android=208.0=20?= =?UTF-8?q?=E4=B8=AD=EF=BC=8C=E5=A6=82=E6=9E=9C=E7=B3=BB=E7=BB=9F=E5=B7=B2?= =?UTF-8?q?=E5=BC=80=E5=90=AF=E8=87=AA=E5=8A=A8=E5=A1=AB=E5=85=85=E6=A1=86?= =?UTF-8?q?=E6=9E=B6=EF=BC=8C=E7=82=B9=E5=87=BB=E5=BE=AE=E4=BF=A1=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=8C=89=E9=92=AE=E9=97=AA=E9=80=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/core/InvocationStubManager.java | 2 + .../proxies/view/AutoFillManagerStub.java | 83 +++++++++++++++++++ .../mirror/android/view/IAutoFillManager.java | 24 ++++++ 3 files changed, 109 insertions(+) create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/view/AutoFillManagerStub.java create mode 100644 VirtualApp/lib/src/main/java/mirror/android/view/IAutoFillManager.java diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java index 55cc89fab..ca728d2ab 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java @@ -47,6 +47,7 @@ import com.lody.virtual.client.hook.proxies.usage.UsageStatsManagerStub; import com.lody.virtual.client.hook.proxies.user.UserManagerStub; import com.lody.virtual.client.hook.proxies.vibrator.VibratorStub; +import com.lody.virtual.client.hook.proxies.view.AutoFillManagerStub; import com.lody.virtual.client.hook.proxies.wifi.WifiManagerStub; import com.lody.virtual.client.hook.proxies.wifi_scanner.WifiScannerStub; import com.lody.virtual.client.hook.proxies.window.WindowManagerStub; @@ -178,6 +179,7 @@ private void injectInternal() throws Throwable { addInjector(new WifiScannerStub()); addInjector(new ShortcutServiceStub()); addInjector(new DevicePolicyManagerStub()); + addInjector(new AutoFillManagerStub()); } } } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/view/AutoFillManagerStub.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/view/AutoFillManagerStub.java new file mode 100644 index 000000000..27c898c2c --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/view/AutoFillManagerStub.java @@ -0,0 +1,83 @@ +package com.lody.virtual.client.hook.proxies.view; + +import android.annotation.SuppressLint; +import android.util.Log; + +import com.lody.virtual.client.hook.base.BinderInvocationProxy; +import com.lody.virtual.client.hook.base.MethodProxy; +import com.lody.virtual.client.hook.utils.MethodParameterUtils; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import mirror.android.view.IAutoFillManager; + +/** + * @author 陈磊. + */ + +public class AutoFillManagerStub extends BinderInvocationProxy { + + private static final String TAG = "AutoFillManagerStub"; + + private static final String AUTO_FILL_NAME = "autofill"; + public AutoFillManagerStub() { + super(IAutoFillManager.Stub.asInterface, AUTO_FILL_NAME); + } + + @SuppressLint("WrongConstant") + @Override + public void inject() throws Throwable { + super.inject(); + try { + Object AutoFillManagerInstance = getContext().getSystemService(AUTO_FILL_NAME); + if (AutoFillManagerInstance == null) { + throw new NullPointerException("AutoFillManagerInstance is null."); + } + Object AutoFillManagerProxy = getInvocationStub().getProxyInterface(); + if (AutoFillManagerProxy == null) { + throw new NullPointerException("AutoFillManagerProxy is null."); + } + Field AutoFillManagerServiceField = AutoFillManagerInstance.getClass().getDeclaredField("mService"); + AutoFillManagerServiceField.setAccessible(true); + AutoFillManagerServiceField.set(AutoFillManagerInstance, AutoFillManagerProxy); + } catch (Throwable tr) { + Log.e(TAG, "AutoFillManagerStub inject error.", tr); + return; + } + addMethodProxy(new MethodProxy() { + @Override + public String getMethodName() { + return "startSession"; + } + @Override + public boolean beforeCall(Object who, Method method, Object... args) { + MethodParameterUtils.replaceLastAppPkg(args); + return super.beforeCall(who, method, args); + } + }); + addMethodProxy(new MethodProxy() { + @Override + public String getMethodName() { + return "updateOrRestartSession"; + } + @Override + public boolean beforeCall(Object who, Method method, Object... args) { + MethodParameterUtils.replaceLastAppPkg(args); + return super.beforeCall(who, method, args); + } + }); + addMethodProxy(new MethodProxy() { + @Override + public String getMethodName() { + return "isServiceEnabled"; + } + @Override + public boolean beforeCall(Object who, Method method, Object... args) { + MethodParameterUtils.replaceLastAppPkg(args); + return super.beforeCall(who, method, args); + } + }); + } + +} diff --git a/VirtualApp/lib/src/main/java/mirror/android/view/IAutoFillManager.java b/VirtualApp/lib/src/main/java/mirror/android/view/IAutoFillManager.java new file mode 100644 index 000000000..2669e4497 --- /dev/null +++ b/VirtualApp/lib/src/main/java/mirror/android/view/IAutoFillManager.java @@ -0,0 +1,24 @@ +package mirror.android.view; + +import android.os.IBinder; +import android.os.IInterface; + +import mirror.MethodParams; +import mirror.RefClass; +import mirror.RefStaticMethod; + +/** + * @author 陈磊. + */ + +public class IAutoFillManager { + + public static Class TYPE = RefClass.load(IAutoFillManager.class, "android.view.autofill.IAutoFillManager"); + + public static class Stub { + public static Class TYPE = RefClass.load(Stub.class, "android.view.autofill.IAutoFillManager$Stub"); + @MethodParams(IBinder.class) + public static RefStaticMethod asInterface; + } + +} From 3a1bee8f94c120ae4819a32cd0c763fc27d5fe51 Mon Sep 17 00:00:00 2001 From: asLody Date: Wed, 13 Dec 2017 12:00:01 +0800 Subject: [PATCH 022/334] Feature: memory scan API. --- VirtualApp/build.gradle | 2 +- .../server/memory/MappedMemoryRegion.java | 47 ++++++++ .../server/memory/MemoryRegionParser.java | 70 +++++++++++ .../server/memory/MemoryScanEngine.java | 111 ++++++++++++++++++ .../virtual/server/memory/MemoryValue.java | 67 +++++++++++ .../virtual/server/memory/ProcessMemory.java | 33 ++++++ 6 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MappedMemoryRegion.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryRegionParser.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryScanEngine.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryValue.java create mode 100644 VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/ProcessMemory.java diff --git a/VirtualApp/build.gradle b/VirtualApp/build.gradle index a9b5ed8ba..cc3fc8ce5 100644 --- a/VirtualApp/build.gradle +++ b/VirtualApp/build.gradle @@ -9,7 +9,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0' + classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle-experimental:0.11.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MappedMemoryRegion.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MappedMemoryRegion.java new file mode 100644 index 000000000..832707fdc --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MappedMemoryRegion.java @@ -0,0 +1,47 @@ +package com.lody.virtual.server.memory; + +/** + * @author Lody + */ +public class MappedMemoryRegion { + + public static class FileMapping { + public final long offset; + public final long majorDeviceNumber; + public final long minorDeviceNumber; + public final long inode; + + public FileMapping(long off, long major, long minor, long inode) { + this.offset = off; + this.majorDeviceNumber = major; + this.minorDeviceNumber = minor; + this.inode = inode; + } + } + + public final long startAddress; + public final long endAddress; + public final boolean isReadable; + public final boolean isWritable; + public final boolean isExecutable; + public final boolean isShared; + + public final FileMapping fileMapInfo; + + public final String description; + + public MappedMemoryRegion(long start, long end, boolean read, boolean write, boolean exec, boolean shared, long off, long majorDevNum, long minorDevNum, long inode, String desc) { + this.startAddress = start; + this.endAddress = end; + this.isReadable = read; + this.isWritable = write; + this.isExecutable = exec; + this.isShared = shared; + this.fileMapInfo = (inode == 0) ? null : new FileMapping(off, majorDevNum, minorDevNum, inode); + this.description = desc; + } + + public boolean isMappedFromFile() { + return this.fileMapInfo != null; + } +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryRegionParser.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryRegionParser.java new file mode 100644 index 000000000..5491db5bd --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryRegionParser.java @@ -0,0 +1,70 @@ +package com.lody.virtual.server.memory; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Lody + */ +public class MemoryRegionParser { + /** + * Regular Expression for /proc/self/maps line is + *

+ * ([0-9a-f]+) - ([0-9a-f]+) \s ([r-]) ([w-]) ([x-]) ([sp]) \s ([0-9a-f]+) \s ([0-9a-f]+) : ([0-9a-f]+) \s (\d+) \s? (.*) + * StartAddress EndAddress Read Write Execute Shared Filemap Offset Major devnum Minor devnum Inode Description + */ + public static final String PATTERN = "([0-9a-f]+)-([0-9a-f]+)\\s([r-])([w-])([x-])([sp])\\s([0-9a-f]+)\\s([0-9a-f]+):([0-9a-f]+)\\s(\\d+)\\s?(.*)"; + public final static Pattern MAPS_LINE_PATTERN = Pattern.compile(PATTERN, Pattern.CASE_INSENSITIVE); + + private static long parseHex(String s) { + return Long.parseLong(s, 16); + } + + private static MappedMemoryRegion parseMapLine(String line) { + line = line.trim(); + Matcher m = MAPS_LINE_PATTERN.matcher(line); + if (!m.matches()) { + throw new IllegalArgumentException(String.format("The provided line does not match the pattern for /proc/$pid/maps lines. Given: %s", line)); + } + + if (m.groupCount() != 11) // group(0) not included in this. + { + throw new InternalError(String.format(Locale.ENGLISH, "Invalid group count: Found %d, but expected %d", m.groupCount(), 12)); + } + + long start = parseHex(m.group(1)); + long end = parseHex(m.group(2)); + boolean read = m.group(3).equals("r"); + boolean write = m.group(4).equals("w"); + boolean exec = m.group(5).equals("x"); + boolean shared = m.group(6).equals("s"); + long fileOffset = parseHex(m.group(7)); + long majorDevNum = parseHex(m.group(8)); + long minorDevNum = parseHex(m.group(9)); + long inode = parseHex(m.group(10)); + String desc = m.group(11); + + return new MappedMemoryRegion(start, end, read, write, exec, shared, fileOffset, majorDevNum, minorDevNum, inode, desc); + } + + + public static List getMemoryRegions(int pid) throws IOException { + List list = new LinkedList<>(); + BufferedReader reader = new BufferedReader(new FileReader(String.format(Locale.ENGLISH, "/proc/%d/maps", pid))); + String line; + while ((line = reader.readLine()) != null) { + MappedMemoryRegion region = parseMapLine(line); + if (region.isReadable && region.isWritable && !region.description.endsWith("(deleted)")) { + list.add(region); + } + } + return list; + } +} \ No newline at end of file diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryScanEngine.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryScanEngine.java new file mode 100644 index 000000000..c9b21c385 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryScanEngine.java @@ -0,0 +1,111 @@ +package com.lody.virtual.server.memory; + +import com.lody.virtual.helper.utils.VLog; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +/** + * @author Lody + */ +public class MemoryScanEngine { + + private List regions; + + private int pid; + private ProcessMemory memory; + private static final int PAGE = 4096; + private List matches; + + public MemoryScanEngine(int pid) throws IOException { + this.pid = pid; + this.memory = new ProcessMemory(pid); + updateMemoryLayout(); + } + + public void updateMemoryLayout() { + try { + regions = MemoryRegionParser.getMemoryRegions(pid); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public List getMatches() { + return matches; + } + + public void search(MemoryValue value) throws IOException { + matches = new LinkedList<>(); + byte[] bytes = new byte[PAGE]; + byte[] valueBytes = value.toBytes(); + for (MappedMemoryRegion region : regions) { + long start = region.startAddress; + long end = region.endAddress; + try { + while (start < end) { + int read = Math.min(bytes.length, (int) (end - start)); + read = memory.read(start, bytes, read); + matches.addAll(matchBytes(region, start, bytes, read, valueBytes)); + start += PAGE; + } + } catch (IOException e) { + VLog.e(getClass().getSimpleName(), "Unable to read region : " + region.description); + } + } + } + + public void modify(Match match, MemoryValue value) throws IOException { + memory.write(match.address, value.toBytes()); + } + + public void modifyAll(MemoryValue value) throws IOException { + for (Match match : matches) { + modify(match, value); + } + } + + public class Match { + MappedMemoryRegion region; + long address; + int len; + + public Match(MappedMemoryRegion region, long address, int len) { + this.region = region; + this.address = address; + this.len = len; + } + } + + + private List matchBytes(MappedMemoryRegion region, long startAddress, byte[] page, int read, byte[] value) { + List matches = new LinkedList<>(); + int start = 0; + int len = value.length; + int step = 2; + while (start < read) { + boolean match = true; + for (int i = 0; i < len && i + start < read; i++) { + if (page[start + i] != value[i]) { + match = false; + break; + } + } + if (match) { + matches.add(new Match(region, startAddress + start, len)); + } + start += step; + } + return matches; + } + + + public void close() { + try { + memory.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryValue.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryValue.java new file mode 100644 index 000000000..59f7cd3c8 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/MemoryValue.java @@ -0,0 +1,67 @@ +package com.lody.virtual.server.memory; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * @author Lody + */ +public abstract class MemoryValue { + + private static final ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN; + + public enum ValueType { + INT2, // short + INT4, // int + INT8, // long + } + + public abstract byte[] toBytes(); + + + public static class INT2 extends MemoryValue { + + private short val; + + public INT2(short val) { + this.val = val; + } + + @Override + public byte[] toBytes() { + ByteBuffer buffer = ByteBuffer.allocate(2); + return buffer.putShort(val).order(BYTE_ORDER).array(); + } + } + + public static class INT4 extends MemoryValue { + + private int val; + + public INT4(int val) { + this.val = val; + } + + @Override + public byte[] toBytes() { + ByteBuffer buffer = ByteBuffer.allocate(4); + return buffer.order(BYTE_ORDER).putInt(val).array(); + } + } + + public static class INT8 extends MemoryValue { + + private long val; + + public INT8(long val) { + this.val = val; + } + + @Override + public byte[] toBytes() { + ByteBuffer buffer = ByteBuffer.allocate(8); + return buffer.order(BYTE_ORDER).putLong(val).array(); + } + } + +} diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/ProcessMemory.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/ProcessMemory.java new file mode 100644 index 000000000..0c86baae5 --- /dev/null +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/memory/ProcessMemory.java @@ -0,0 +1,33 @@ +package com.lody.virtual.server.memory; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Locale; + +/** + * @author Lody + */ +public class ProcessMemory { + + private int pid; + private RandomAccessFile memFile; + + public ProcessMemory(int pid) throws IOException { + this.pid = pid; + this.memFile = new RandomAccessFile(String.format(Locale.ENGLISH, "/proc/%d/mem", pid), "rw"); + } + + public void write(long offset, byte[] bytes) throws IOException { + memFile.seek(offset); + memFile.write(bytes); + } + + public int read(long offset, byte[] bytes, int len) throws IOException { + memFile.seek(offset); + return memFile.read(bytes, 0, len); + } + + public void close() throws IOException { + memFile.close(); + } +} From 9141f8b8e10d755629fda7e48c38a0a98b72c46a Mon Sep 17 00:00:00 2001 From: "monch.chen@yahoo.com" Date: Wed, 13 Dec 2017 16:57:03 +0800 Subject: [PATCH 023/334] =?UTF-8?q?=E4=BF=AE=E6=94=B9SDK=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/lody/virtual/client/core/InvocationStubManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java index ca728d2ab..a7712f023 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/core/InvocationStubManager.java @@ -179,8 +179,10 @@ private void injectInternal() throws Throwable { addInjector(new WifiScannerStub()); addInjector(new ShortcutServiceStub()); addInjector(new DevicePolicyManagerStub()); - addInjector(new AutoFillManagerStub()); } + if (Build.VERSION.SDK_INT >= 26) { + addInjector(new AutoFillManagerStub()); + } } } From bae7250cb795d447f41bebe658cec0269ec66111 Mon Sep 17 00:00:00 2001 From: tiann <923551233@qq.com> Date: Fri, 15 Dec 2017 02:21:40 +0800 Subject: [PATCH 024/334] Fix: install error above Android N (support FileProvider) --- .../client/hook/proxies/am/MethodProxies.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java index d49d1052f..a6a415560 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java @@ -55,6 +55,7 @@ import com.lody.virtual.helper.utils.BitmapUtils; import com.lody.virtual.helper.utils.ComponentUtils; import com.lody.virtual.helper.utils.DrawableUtils; +import com.lody.virtual.helper.utils.FileUtils; import com.lody.virtual.helper.utils.Reflect; import com.lody.virtual.helper.utils.VLog; import com.lody.virtual.os.VUserHandle; @@ -63,6 +64,10 @@ import com.lody.virtual.server.interfaces.IAppRequestListener; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.List; @@ -360,6 +365,7 @@ static class StartActivity extends MethodProxy { private static final String SCHEME_FILE = "file"; private static final String SCHEME_PACKAGE = "package"; + private static final String SCHEME_CONTENT = "content"; @Override public String getMethodName() { @@ -475,6 +481,32 @@ private boolean handleInstallRequest(Intent intent) { } catch (RemoteException e) { e.printStackTrace(); } + } else if (SCHEME_CONTENT.equals(packageUri.getScheme())){ + InputStream inputStream = null; + OutputStream outputStream = null; + File sharedFileCopy = new File(getHostContext().getCacheDir(), packageUri.getLastPathSegment()); + try { + inputStream = getHostContext().getContentResolver().openInputStream(packageUri); + outputStream = new FileOutputStream(sharedFileCopy); + byte[] buffer = new byte[1024]; + int count; + while ((count = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, count); + } + outputStream.flush(); + + } catch (IOException e) { + e.printStackTrace(); + } finally { + FileUtils.closeQuietly(inputStream); + FileUtils.closeQuietly(outputStream); + } + try { + listener.onRequestInstall(sharedFileCopy.getPath()); + return true; + } catch (RemoteException e) { + e.printStackTrace(); + } } } From cac45afc39f9895d6e575dd1f3e0c4cbb0dbf19b Mon Sep 17 00:00:00 2001 From: Ruikai Liu Date: Wed, 20 Dec 2017 11:47:43 +0800 Subject: [PATCH 025/334] fix mem leak --- VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 47f216a37..46f17b36a 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -565,6 +565,7 @@ HOOK_DEF(int, execve, const char *pathname, char *argv[], char *const envp[]) { char **new_envp = build_new_env(envp); int ret = syscall(__NR_execve, redirect_path, argv, new_envp); FREE(redirect_path, pathname); + free(new_envp); return ret; } int ret = syscall(__NR_execve, redirect_path, argv, envp); From 8e6d9cd925af55b53a7e93046c469dd69676c38b Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 04:33:41 -0600 Subject: [PATCH 026/334] Update CHINESE.md --- CHINESE.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 0eea6c684..ace08272e 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,13 +14,18 @@ VA目前被广泛应用于双开/多开、应用市场、模拟定位、一键 申明 --- -VirtualApp开放源代码只能用于个人技术研究和开拓思路。当您需要将VirtualApp用于商业用途时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于商业牟利、内部使用或上传软件市场,我们将直接报警(侵犯著作权罪)。 - -购买商业授权是对我们最大的支持和认可,同时也为您节省了大量的开发完善时间,保障您的产品可以高效的上线运营,让您有更多的时间去创新和盈利。作为购买商业授权的回报,您可以获得说明文档、未开放的商业版和专人1vs1对接项目(全年24小时随时微信群、QQ群、电话等1vs1负责制,保证响应时间。包括:接入对接、BUG解决、技术解答、运营建议、同行非保密运营信息分享(营收、经验、推广、弯路)、涉足行业预警)!同时我们也支持基于VirtualApp的订制开发,请联系:QQ:10890 洽谈。 - -请注意 ------ -VirtualApp代码的更新频率非常快(`以小时为单位`),每一次代码的更新都有可能修复重大BUG,所以请 `watch` 本项目,并注意随时更新代码,以免给您带来损失! +VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于商业牟利、内部使用或上传软件市场,我们将直接报警(侵犯著作权罪),这将对您所属的公司造成法律诉讼和刑事责任,影响到您公司的商誉和投资。 +  +购买商业授权为您节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。VirtualApp源代码将于2017年12月31日停止更新。 +  +商业版更新日志: +2017年12月28日 +1、增加了定位代码 +2、代码进行了架构优化 +3、与开源版不同的特征 +4、解决了微信被封的一些问题 +5、修复了部分机型兼容性 +6、修复了12个小BUG 已支持的加固(不断更新) @@ -92,6 +97,6 @@ MicroG的必要模块: VirtualCore.getCore().findApp({PackageName}); ``` -技术支持 +BUG反馈 ------------ -QQ群:598536 +zlu@QQ.com From 63b78e450567249d95b86ac6e33a0baa7f894344 Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 04:34:07 -0600 Subject: [PATCH 027/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index ace08272e..eac6b56c0 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -20,11 +20,17 @@ VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要   商业版更新日志: 2017年12月28日 + 1、增加了定位代码 + 2、代码进行了架构优化 + 3、与开源版不同的特征 + 4、解决了微信被封的一些问题 + 5、修复了部分机型兼容性 + 6、修复了12个小BUG From 12604f7cc3bfacf4fef494ede47c05fcbdc2b88f Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 04:34:30 -0600 Subject: [PATCH 028/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index eac6b56c0..5ddd655ec 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -19,6 +19,7 @@ VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要 购买商业授权为您节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。VirtualApp源代码将于2017年12月31日停止更新。   商业版更新日志: + 2017年12月28日 1、增加了定位代码 From 166bfe68200367543c3da5a48b297b22ba6d50ee Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 04:34:47 -0600 Subject: [PATCH 029/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 5ddd655ec..8f749076c 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -18,6 +18,7 @@ VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要   购买商业授权为您节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。VirtualApp源代码将于2017年12月31日停止更新。   + 商业版更新日志: 2017年12月28日 From edeba11e9a3d44f8852a197108b68f0d12bbc485 Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 04:41:39 -0600 Subject: [PATCH 030/334] Update CHINESE.md --- CHINESE.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 8f749076c..d7fcf0217 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -22,18 +22,12 @@ VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要 商业版更新日志: 2017年12月28日 - -1、增加了定位代码 - -2、代码进行了架构优化 - -3、与开源版不同的特征 - -4、解决了微信被封的一些问题 - -5、修复了部分机型兼容性 - -6、修复了12个小BUG +1. 增加了定位代码 +2. 代码进行了架构优化 +3. 与开源版不同的特征 +4. 解决了微信被封的一些问题 +5. 修复了部分机型兼容性 +6. 修复了12个小BUG 已支持的加固(不断更新) From 59579763403ffd46f2159dea54e769bf668022e8 Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 04:42:52 -0600 Subject: [PATCH 031/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index d7fcf0217..7a4143b0a 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -21,7 +21,7 @@ VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要 商业版更新日志: -2017年12月28日 +**2017年12月28日** 1. 增加了定位代码 2. 代码进行了架构优化 3. 与开源版不同的特征 From 07a88bc6b4f8302670fd1590c2bf1eaccb698004 Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 04:44:17 -0600 Subject: [PATCH 032/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e96791aac..89976f116 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Documentation VirtualApp currently has **no documentation**, If you are interested in VirtualApp, please send email to me. -About Author +Contact us ------------ - Lody (imlody@foxmail.com) + zlu@QQ.com From 8ad41e84a9d7cdc5a09b78e6df503a62c33fce89 Mon Sep 17 00:00:00 2001 From: Lody <2523313136@qq.com> Date: Sat, 30 Dec 2017 05:34:38 -0600 Subject: [PATCH 033/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 7a4143b0a..ba031f447 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -16,7 +16,7 @@ VA目前被广泛应用于双开/多开、应用市场、模拟定位、一键 --- VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于商业牟利、内部使用或上传软件市场,我们将直接报警(侵犯著作权罪),这将对您所属的公司造成法律诉讼和刑事责任,影响到您公司的商誉和投资。   -购买商业授权为您节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。VirtualApp源代码将于2017年12月31日停止更新。 +购买商业授权为您节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。VirtualApp对外开放的源代码将于2017年12月31日停止更新,VirtualApp商业版代码将持续更新!   商业版更新日志: From 60a2748bef4a76fe22b3e7220db4ccbd9cef58fc Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Tue, 9 Jan 2018 12:02:57 +0800 Subject: [PATCH 034/334] CHINESE.md --- CHINESE.md | 12 ++++++++++-- README.md | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index ba031f447..23e26dbe9 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,13 +14,21 @@ VA目前被广泛应用于双开/多开、应用市场、模拟定位、一键 申明 --- -VirtualApp(中文名:罗盒)2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于商业牟利、内部使用或上传软件市场,我们将直接报警(侵犯著作权罪),这将对您所属的公司造成法律诉讼和刑事责任,影响到您公司的商誉和投资。 +VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于商业牟利、内部使用或上传软件市场,我们将直接报警(侵犯著作权罪),这将对您所属的公司造成法律诉讼和刑事责任,影响到您公司的商誉和投资。   购买商业授权为您节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。VirtualApp对外开放的源代码将于2017年12月31日停止更新,VirtualApp商业版代码将持续更新!   商业版更新日志: +**2018年01月08日** +1. 完善定位(支持探探,QQ,微信) +2. 设置手机信息,imei伪装算法 +3. 适配8.0某个功能(主要app:whatsapp) +4. 修复内部微信等应用,无法更新图片,视频 +5. demo增加安装监听,自动升级克隆模式的应用 +6. 7.0的file provider适配 + **2017年12月28日** 1. 增加了定位代码 2. 代码进行了架构优化 @@ -101,4 +109,4 @@ MicroG的必要模块: BUG反馈 ------------ -zlu@QQ.com +zl@aluohe.com diff --git a/README.md b/README.md index 89976f116..24a891a42 100644 --- a/README.md +++ b/README.md @@ -73,4 +73,4 @@ VirtualApp currently has **no documentation**, If you are interested in VirtualA Contact us ------------ - zlu@QQ.com + zl@aluohe.com From 878994517c9c3f9ed64cac0dce5fa6f1d1ab532d Mon Sep 17 00:00:00 2001 From: asLody Date: Tue, 9 Jan 2018 13:41:01 +0800 Subject: [PATCH 035/334] Fix: huawei 8.0 broadcast problem. --- .../com/lody/virtual/server/am/BroadcastSystem.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java index 10e285e5f..8d7a98251 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/am/BroadcastSystem.java @@ -16,12 +16,14 @@ import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.SpecialComponentList; import com.lody.virtual.helper.collection.ArrayMap; +import com.lody.virtual.helper.utils.Reflect; import com.lody.virtual.helper.utils.VLog; import com.lody.virtual.remote.PendingResultData; import com.lody.virtual.server.pm.PackageSetting; import com.lody.virtual.server.pm.VAppManagerService; import com.lody.virtual.server.pm.parser.VPackage; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -103,7 +105,15 @@ private void fuckHuaWeiVerifier() { if (packageInfo != null) { Object receiverResource = LoadedApkHuaWei.mReceiverResource.get(packageInfo); if (receiverResource != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (Build.VERSION.SDK_INT >= 26) { + Map> whiteListMap = Reflect.on(receiverResource).get("mWhiteListMap"); + List whiteList = whiteListMap.get(0); + if (whiteList == null) { + whiteList = new ArrayList<>(); + whiteListMap.put(0, whiteList); + } + whiteList.add(mContext.getPackageName()); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (ReceiverResourceN.mWhiteList != null) { List whiteList = ReceiverResourceN.mWhiteList.get(receiverResource); List newWhiteList = new ArrayList<>(); @@ -114,7 +124,6 @@ private void fuckHuaWeiVerifier() { } ReceiverResourceN.mWhiteList.set(receiverResource, newWhiteList); } - } else { if (ReceiverResourceM.mWhiteList != null) { String[] whiteList = ReceiverResourceM.mWhiteList.get(receiverResource); From 9b3af63d1dbca63f3c6a5446c9adad8662ad85eb Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Tue, 9 Jan 2018 13:50:32 +0800 Subject: [PATCH 036/334] CHINESE.md --- CHINESE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 23e26dbe9..3c5c867bc 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -21,6 +21,9 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 商业版更新日志: +**2018年01月09日** +1. 修复8.0的一个致命bug + **2018年01月08日** 1. 完善定位(支持探探,QQ,微信) 2. 设置手机信息,imei伪装算法 From 1cca149af9c8212aebb06c51e9b652b9ee3ae499 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Tue, 9 Jan 2018 14:20:39 +0800 Subject: [PATCH 037/334] CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 3c5c867bc..dd22c810f 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -22,7 +22,7 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 商业版更新日志: **2018年01月09日** -1. 修复8.0的一个致命bug +1. 修复华为emui8.0的一个bug **2018年01月08日** 1. 完善定位(支持探探,QQ,微信) From 67fb86905b3d05bbbb229ffae18d492f5d58115b Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Wed, 10 Jan 2018 09:33:46 +0800 Subject: [PATCH 038/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index dd22c810f..02a7f3c65 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -25,7 +25,7 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 1. 修复华为emui8.0的一个bug **2018年01月08日** -1. 完善定位(支持探探,QQ,微信) +1. 完善定位 2. 设置手机信息,imei伪装算法 3. 适配8.0某个功能(主要app:whatsapp) 4. 修复内部微信等应用,无法更新图片,视频 From 9428ad79a5ba0fa341d98b41daec59021d6c32b3 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Sat, 20 Jan 2018 16:40:10 +0800 Subject: [PATCH 039/334] CHINESE.md --- CHINESE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index dd22c810f..4d5530984 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -21,6 +21,17 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 商业版更新日志: +**2018年01月15日** +1. jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE +2. 混淆配置 +3. Android O的通知栏适配 + +**2018年01月14日** +1. 修复部分app网络卡的问题 + +**2018年01月12日** +1、适配 android 8.0的dl_open(jni加载) + **2018年01月09日** 1. 修复华为emui8.0的一个bug From 28186e04435bdd16d82b2da79107758d2b7fd977 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Mon, 22 Jan 2018 11:44:55 +0800 Subject: [PATCH 040/334] CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index a801896ef..d2e4daadc 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -30,7 +30,7 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 1. 修复部分app网络卡的问题 **2018年01月12日** -1、适配 android 8.0的dl_open(jni加载) +1. 适配 android 8.0的dl_open(jni加载) **2018年01月09日** 1. 修复华为emui8.0的一个bug From 8e06710945437576e25462d2a69c659690a3365b Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Mon, 29 Jan 2018 17:52:05 +0800 Subject: [PATCH 041/334] CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index d2e4daadc..8a3a9f1f4 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -21,6 +21,12 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 商业版更新日志: +**2018年01月29日** +1. Android O的通知栏适配2 + +**2018年01月22日** +1. ipc框架优化, 提高判断binder的存活准确性 + **2018年01月15日** 1. jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE 2. 混淆配置 From f4ffe56955b2db4414876abfe9576616c3d59cc8 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Sun, 4 Feb 2018 17:43:56 +0800 Subject: [PATCH 042/334] CHINESE.md disable google serivce --- CHINESE.md | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 12e0613cf..17e189c62 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -4,7 +4,7 @@ --- **VirtualApp**是一个**App虚拟化引擎**(简称`VA`)。 -**VirtualApp已兼容Android 0(8.0 Preview)。** +**VirtualApp已兼容Android 0(8.0)。** VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 @@ -36,26 +36,9 @@ VirtualApp代码的更新频率非常快(`以小时为单位`),每一次 * (已支持的加固均可通过VA来脱壳,本技术不公开) -在VA使用Google服务 +Google Play Framework ----------- -VA支持运行官方的Google服务套件,同时我们也提供了对`MicroG`的支持。 - -您可以通过在VA中安装`MicroG`来支持`Google服务`, - -这样,即使外部没有Google服务,用户也可以在VA中享受Google服务。 - -MicroG套件可在此下载:[Download MicroG](https://microg.org/download.html) - -MicroG的必要模块: -* Services Core -* Services Framework Proxy -* Store - -如果您需要在VA中使用官方的Google服务套件(外部已安装的前提下), - -则可以通过 `GmsSupport.installGms(userId)` 来安装。 - -##### 注意,您不能同时安装MicroGms和官方的Gms。 +在google service新版本,存在兼容适配问题,暂时屏蔽 使用说明 From 3af013add84730e0cde857bf7d803f75e5db64c4 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Mon, 5 Feb 2018 16:57:40 +0800 Subject: [PATCH 043/334] CHINESE.md --- CHINESE.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index bdde89d0c..a6819124b 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -21,6 +21,13 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 商业版更新日志: +**2017年02月05日** +1. 前台服务的通知栏拦截开关 +2. 附带doc + +**2017年02月03日** +1. 完善VA内部的intent的CHOOSE回调 + **2018年01月29日** 1. Android O的通知栏适配2 From 912e57ed738e8391874c472f0080f0baa0fdf31b Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Mon, 5 Feb 2018 17:37:31 +0800 Subject: [PATCH 044/334] CHINESE.md --- CHINESE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index a6819124b..f2670520a 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -21,11 +21,11 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 商业版更新日志: -**2017年02月05日** +**2018年02月05日** 1. 前台服务的通知栏拦截开关 2. 附带doc -**2017年02月03日** +**2018年02月03日** 1. 完善VA内部的intent的CHOOSE回调 **2018年01月29日** From 7af5a8929f4b71de99876e8f221d8721f8246cae Mon Sep 17 00:00:00 2001 From: keyongyu <247321453@qq.com> Date: Wed, 7 Feb 2018 10:48:07 +0800 Subject: [PATCH 045/334] CHINESE.md --- CHINESE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index f2670520a..63672a1c6 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -21,6 +21,10 @@ VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用 商业版更新日志: +**2018年02月07日** +1. 分享的uri处理 +2. 修复跨app调用Activity的回调 + **2018年02月05日** 1. 前台服务的通知栏拦截开关 2. 附带doc From 31559f6b57faf02f5409657bd2f97e12f52324bd Mon Sep 17 00:00:00 2001 From: Liu Shuai Date: Wed, 7 Feb 2018 16:22:21 +0800 Subject: [PATCH 046/334] fixed Hook BluetoothAdapter#getAddress failed >= JELLY_BEAN_MR1 --- .../hook/proxies/bluetooth/BluetoothStub.java | 4 +++- .../android/bluetooth/IBluetoothManager.java | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 VirtualApp/lib/src/main/java/mirror/android/bluetooth/IBluetoothManager.java diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/bluetooth/BluetoothStub.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/bluetooth/BluetoothStub.java index 9590cab43..1eb15b4ff 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/bluetooth/BluetoothStub.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/bluetooth/BluetoothStub.java @@ -9,6 +9,7 @@ import java.lang.reflect.Method; import mirror.android.bluetooth.IBluetooth; +import mirror.android.bluetooth.IBluetoothManager; /** * @see android.bluetooth.BluetoothManager @@ -19,7 +20,8 @@ public class BluetoothStub extends BinderInvocationProxy { "bluetooth"; public BluetoothStub() { - super(IBluetooth.Stub.asInterface, SERVICE_NAME); + super(Build.VERSION.SDK_INT >= 17 ? IBluetoothManager.Stub.asInterface : IBluetooth.Stub.asInterface, + SERVICE_NAME); } @Override diff --git a/VirtualApp/lib/src/main/java/mirror/android/bluetooth/IBluetoothManager.java b/VirtualApp/lib/src/main/java/mirror/android/bluetooth/IBluetoothManager.java new file mode 100644 index 000000000..ad06679ca --- /dev/null +++ b/VirtualApp/lib/src/main/java/mirror/android/bluetooth/IBluetoothManager.java @@ -0,0 +1,23 @@ +package mirror.android.bluetooth; + +import android.os.IBinder; +import android.os.IInterface; + +import mirror.MethodParams; +import mirror.RefClass; +import mirror.RefStaticMethod; + +public class IBluetoothManager { + /** + * @see android.bluetooth.IBluetoothManager + * */ + public static Class TYPE = RefClass.load(IBluetoothManager.class, "android.bluetooth.IBluetoothManager"); + /** + * @see android.bluetooth.IBluetoothManager.Stub + * */ + public static class Stub { + public static Class TYPE = RefClass.load(Stub.class, "android.bluetooth.IBluetoothManager$Stub"); + @MethodParams({IBinder.class}) + public static RefStaticMethod asInterface; + } +} From d542c8ddb5d0bd6ab0be05ea1e02d6eda1fdd405 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Thu, 1 Mar 2018 20:02:13 +0800 Subject: [PATCH 047/334] CHINESE.md --- CHINESE.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 63672a1c6..5bcb4c16d 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,10 +14,14 @@ VA目前被广泛应用于双开/多开、应用市场、模拟定位、一键 申明 --- -VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请务必联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于商业牟利、内部使用或上传软件市场,我们将直接报警(侵犯著作权罪),这将对您所属的公司造成法律诉讼和刑事责任,影响到您公司的商誉和投资。 -  -购买商业授权为您节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。VirtualApp对外开放的源代码将于2017年12月31日停止更新,VirtualApp商业版代码将持续更新! -  +VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传软件市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。 + +目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您所在公司节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。
+
+负责人:张总
+手机:130-321-77777
+Q Q:10890
+ 商业版更新日志: From b11b29539cb8e44b9fc143e688b9b9d847297dab Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Sat, 3 Mar 2018 22:41:20 +0800 Subject: [PATCH 048/334] CHINESE.md --- CHINESE.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 5bcb4c16d..4494c30fd 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,17 +14,23 @@ VA目前被广泛应用于双开/多开、应用市场、模拟定位、一键 申明 --- -VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传软件市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。 - -目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您所在公司节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。VirtualApp商业授权包含:商业版代码、说明接入文档、微信和QQ群全年技术支持。
+VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传软件市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。
+
+目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您所在公司节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。获取VirtualApp商业授权后您将得到:商业版代码、说明接入文档、微信和QQ群技术支持。

负责人:张总
手机:130-321-77777
-Q Q:10890
+Q Q:10890
+
+商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
商业版更新日志: +**2018年03月02日** +1. 修复某些情况下MediaController的bug +2. 修复4.1.2的StubFileProvider报错 + **2018年02月07日** 1. 分享的uri处理 2. 修复跨app调用Activity的回调 From 6b4bca36248daa51b1e41c7ac8eef1f194430a35 Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Wed, 7 Mar 2018 10:39:04 +0800 Subject: [PATCH 049/334] Update CHINESE.md --- CHINESE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 4494c30fd..2d4453258 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,6 +27,11 @@ Q Q:10890
商业版更新日志: +**2018年03月07日** +1. 适配android O 快捷方式 +2. 适配耳机模式 +3. 某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 + **2018年03月02日** 1. 修复某些情况下MediaController的bug 2. 修复4.1.2的StubFileProvider报错 From 7f32ab15d0256b540d1943d13611c0c07892099b Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Wed, 7 Mar 2018 10:47:09 +0800 Subject: [PATCH 050/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 2d4453258..afcf7aebb 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -31,6 +31,7 @@ Q Q:10890
1. 适配android O 快捷方式 2. 适配耳机模式 3. 某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 +4. 修复多开情况下一个bug **2018年03月02日** 1. 修复某些情况下MediaController的bug From f87705a0f47997bac5a7aff7f4b6907e1939484d Mon Sep 17 00:00:00 2001 From: keyongyu <247321453@qq.com> Date: Mon, 12 Mar 2018 20:04:11 +0800 Subject: [PATCH 051/334] CHINESE.md --- CHINESE.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index afcf7aebb..a2c861a12 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,6 +27,18 @@ Q Q:10890
商业版更新日志: +**2018年03月12日** +1. 改善进程初始化代码,增加稳定性 + +**2018年03月11日** +1. 添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 + +**2018年03月09日** +1. 适配关联google play游戏,支持游戏使用google登录 + +**2018年03月08日** +1. 适配android O的google service框架 + **2018年03月07日** 1. 适配android O 快捷方式 2. 适配耳机模式 From e3586f4310ecc2451c1a98b1c1d16c2c31a309e5 Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Wed, 14 Mar 2018 07:09:38 +0000 Subject: [PATCH 052/334] Update CHINESE.md --- CHINESE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index a2c861a12..2cbcb98c0 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,6 +27,11 @@ Q Q:10890
商业版更新日志: +**2018年03月13日** +1.修复某些rom下,快捷方式图标不正确 +2.兼容以前组件StubFileProvider +3.适配部分新ROM的虚拟IMEI + **2018年03月12日** 1. 改善进程初始化代码,增加稳定性 From 0bc07eaa7e7ffca0f34c419671987aa92f25e828 Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Wed, 14 Mar 2018 07:10:34 +0000 Subject: [PATCH 053/334] Update CHINESE.md --- CHINESE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 2cbcb98c0..6a3041071 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -28,9 +28,9 @@ Q Q:10890
商业版更新日志: **2018年03月13日** -1.修复某些rom下,快捷方式图标不正确 -2.兼容以前组件StubFileProvider -3.适配部分新ROM的虚拟IMEI +1. 修复某些rom下,快捷方式图标不正确 +2. 兼容以前组件StubFileProvider +3. 适配部分新ROM的虚拟IMEI **2018年03月12日** 1. 改善进程初始化代码,增加稳定性 From 5f073ea9a018694cb83967ebc0febcaa82623336 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Tue, 3 Apr 2018 16:59:38 +0800 Subject: [PATCH 054/334] CHINESE.md --- CHINESE.md | 109 ++++++++++++++++++----------------------------------- 1 file changed, 37 insertions(+), 72 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 6a3041071..8d9dbea3c 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,82 +24,47 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
- -商业版更新日志: -**2018年03月13日** +商业版代码更新内容: + 1. 修复某些rom下,快捷方式图标不正确 2. 兼容以前组件StubFileProvider 3. 适配部分新ROM的虚拟IMEI - -**2018年03月12日** -1. 改善进程初始化代码,增加稳定性 - -**2018年03月11日** -1. 添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 - -**2018年03月09日** -1. 适配关联google play游戏,支持游戏使用google登录 - -**2018年03月08日** -1. 适配android O的google service框架 - -**2018年03月07日** -1. 适配android O 快捷方式 -2. 适配耳机模式 -3. 某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 -4. 修复多开情况下一个bug - -**2018年03月02日** -1. 修复某些情况下MediaController的bug -2. 修复4.1.2的StubFileProvider报错 - -**2018年02月07日** -1. 分享的uri处理 -2. 修复跨app调用Activity的回调 - -**2018年02月05日** -1. 前台服务的通知栏拦截开关 -2. 附带doc - -**2018年02月03日** -1. 完善VA内部的intent的CHOOSE回调 - -**2018年01月29日** -1. Android O的通知栏适配2 - -**2018年01月22日** -1. ipc框架优化, 提高判断binder的存活准确性 - -**2018年01月15日** -1. jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE -2. 混淆配置 -3. Android O的通知栏适配 - -**2018年01月14日** -1. 修复部分app网络卡的问题 - -**2018年01月12日** -1. 适配 android 8.0的dl_open(jni加载) - -**2018年01月09日** -1. 修复华为emui8.0的一个bug - -**2018年01月08日** -1. 完善定位 -2. 设置手机信息,imei伪装算法 -3. 适配8.0某个功能(主要app:whatsapp) -4. 修复内部微信等应用,无法更新图片,视频 -5. demo增加安装监听,自动升级克隆模式的应用 -6. 7.0的file provider适配 - -**2017年12月28日** -1. 增加了定位代码 -2. 代码进行了架构优化 -3. 与开源版不同的特征 -4. 解决了微信被封的一些问题 -5. 修复了部分机型兼容性 -6. 修复了12个小BUG +4. 改善进程初始化代码,增加稳定性 +5. 添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 +6. 适配关联google play游戏,支持游戏使用google登录 +7. 适配android O的google service框架 +8. 适配android O 快捷方式 +9. 适配耳机模式 +10. 某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 +11. 修复多开情况下一个bug +12. 修复某些情况下MediaController的bug +13. 修复4.1.2的StubFileProvider报错 +14. 分享的uri处理 +15. 修复跨app调用Activity的回调 +16. 前台服务的通知栏拦截开关 +17. 附带doc +18. 完善VA内部的intent的CHOOSE回调 +19. Android O的通知栏适配2 +20. ipc框架优化, 提高判断binder的存活准确性 +21. jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE +22. 混淆配置 +23. Android O的通知栏适配 +24. 修复部分app网络卡的问题 +25. 适配 android 8.0的dl_open(jni加载) +26. 修复华为emui8.0的一个bug +27. 完善定位 +28. 设置手机信息,imei伪装算法 +29. 适配8.0某个功能(主要app:whatsapp) +30. 修复内部微信等应用,无法更新图片,视频 +31. demo增加安装监听,自动升级克隆模式的应用 +32. 7.0的file provider适配 +33. 增加了定位代码 +34. 代码进行了架构优化 +35. 与开源版不同的特征 +36. 解决了微信被封的一些问题 +37. 修复了部分机型兼容性 +38. 修复了12个小BUG 已支持的加固(不断更新) From b1a0dabdc6f5d1a19667548e0a595b8288cfd340 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Wed, 4 Apr 2018 19:30:36 +0800 Subject: [PATCH 055/334] CHINESE.md --- CHINESE.md | 87 +++++++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 8d9dbea3c..b4719fe80 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -25,46 +25,53 @@ Q Q:10890
商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
-商业版代码更新内容: - -1. 修复某些rom下,快捷方式图标不正确 -2. 兼容以前组件StubFileProvider -3. 适配部分新ROM的虚拟IMEI -4. 改善进程初始化代码,增加稳定性 -5. 添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 -6. 适配关联google play游戏,支持游戏使用google登录 -7. 适配android O的google service框架 -8. 适配android O 快捷方式 -9. 适配耳机模式 -10. 某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 -11. 修复多开情况下一个bug -12. 修复某些情况下MediaController的bug -13. 修复4.1.2的StubFileProvider报错 -14. 分享的uri处理 -15. 修复跨app调用Activity的回调 -16. 前台服务的通知栏拦截开关 -17. 附带doc -18. 完善VA内部的intent的CHOOSE回调 -19. Android O的通知栏适配2 -20. ipc框架优化, 提高判断binder的存活准确性 -21. jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE -22. 混淆配置 -23. Android O的通知栏适配 -24. 修复部分app网络卡的问题 -25. 适配 android 8.0的dl_open(jni加载) -26. 修复华为emui8.0的一个bug -27. 完善定位 -28. 设置手机信息,imei伪装算法 -29. 适配8.0某个功能(主要app:whatsapp) -30. 修复内部微信等应用,无法更新图片,视频 -31. demo增加安装监听,自动升级克隆模式的应用 -32. 7.0的file provider适配 -33. 增加了定位代码 -34. 代码进行了架构优化 -35. 与开源版不同的特征 -36. 解决了微信被封的一些问题 -37. 修复了部分机型兼容性 -38. 修复了12个小BUG +4月4日最新商业版更新: + +1. 修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。 +2. 增加应用的保活机制,双开APP更不易被杀死。 +3. 优化虚拟引擎启动性能。 +4. 兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。 + +商业版代码历史更新: + +38. 修复某些rom下,快捷方式图标不正确 +37. 兼容以前组件StubFileProvider +36. 适配部分新ROM的虚拟IMEI +35. 改善进程初始化代码,增加稳定性 +34. 添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 +33. 适配关联google play游戏,支持游戏使用google登录 +32. 适配android O的google service框架 +31. 适配android O 快捷方式 +30. 适配耳机模式 +29. 某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 +28. 修复多开情况下一个bug +27. 修复某些情况下MediaController的bug +26. 修复4.1.2的StubFileProvider报错 +25. 分享的uri处理 +24. 修复跨app调用Activity的回调 +23. 前台服务的通知栏拦截开关 +22. 附带doc +21. 完善VA内部的intent的CHOOSE回调 +20. Android O的通知栏适配2 +19. ipc框架优化, 提高判断binder的存活准确性 +18. jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE +17. 混淆配置 +16. Android O的通知栏适配 +15. 修复部分app网络卡的问题 +14. 适配 android 8.0的dl_open(jni加载) +13. 修复华为emui8.0的一个bug +12. 完善定位 +11. 设置手机信息,imei伪装算法 +10. 适配8.0某个功能(主要app:whatsapp) +9. 修复内部微信等应用,无法更新图片,视频 +8. demo增加安装监听,自动升级克隆模式的应用 +7. 7.0的file provider适配 +6. 增加了定位代码 +5. 代码进行了架构优化 +4. 与开源版不同的特征 +3. 解决了微信被封的一些问题 +2. 修复了部分机型兼容性 +1. 修复了12个小BUG 已支持的加固(不断更新) From 9efd6958045c6acd0874aca4009884a57fcc79b0 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Wed, 4 Apr 2018 19:32:12 +0800 Subject: [PATCH 056/334] CHINESE.md --- CHINESE.md | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index b4719fe80..3043b689c 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,51 +27,51 @@ Q Q:10890
4月4日最新商业版更新: -1. 修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。 -2. 增加应用的保活机制,双开APP更不易被杀死。 -3. 优化虚拟引擎启动性能。 -4. 兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。 +1、修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。 +2、增加应用的保活机制,双开APP更不易被杀死。 +3、优化虚拟引擎启动性能。 +4、兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。 商业版代码历史更新: -38. 修复某些rom下,快捷方式图标不正确 -37. 兼容以前组件StubFileProvider -36. 适配部分新ROM的虚拟IMEI -35. 改善进程初始化代码,增加稳定性 -34. 添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 -33. 适配关联google play游戏,支持游戏使用google登录 -32. 适配android O的google service框架 -31. 适配android O 快捷方式 -30. 适配耳机模式 -29. 某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 -28. 修复多开情况下一个bug -27. 修复某些情况下MediaController的bug -26. 修复4.1.2的StubFileProvider报错 -25. 分享的uri处理 -24. 修复跨app调用Activity的回调 -23. 前台服务的通知栏拦截开关 -22. 附带doc -21. 完善VA内部的intent的CHOOSE回调 -20. Android O的通知栏适配2 -19. ipc框架优化, 提高判断binder的存活准确性 -18. jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE -17. 混淆配置 -16. Android O的通知栏适配 -15. 修复部分app网络卡的问题 -14. 适配 android 8.0的dl_open(jni加载) -13. 修复华为emui8.0的一个bug -12. 完善定位 -11. 设置手机信息,imei伪装算法 -10. 适配8.0某个功能(主要app:whatsapp) -9. 修复内部微信等应用,无法更新图片,视频 -8. demo增加安装监听,自动升级克隆模式的应用 -7. 7.0的file provider适配 -6. 增加了定位代码 -5. 代码进行了架构优化 -4. 与开源版不同的特征 -3. 解决了微信被封的一些问题 -2. 修复了部分机型兼容性 -1. 修复了12个小BUG +38、修复某些rom下,快捷方式图标不正确 +37、兼容以前组件StubFileProvider +36、适配部分新ROM的虚拟IMEI +35、改善进程初始化代码,增加稳定性 +34、添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 +33、适配关联google play游戏,支持游戏使用google登录 +32、适配android O的google service框架 +31、适配android O 快捷方式 +30、适配耳机模式 +29、某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 +28、修复多开情况下一个bug +27、修复某些情况下MediaController的bug +26、修复4.1.2的StubFileProvider报错 +25、分享的uri处理 +24、修复跨app调用Activity的回调 +23、前台服务的通知栏拦截开关 +22、附带doc +21、完善VA内部的intent的CHOOSE回调 +20、Android O的通知栏适配2 +19、ipc框架优化, 提高判断binder的存活准确性 +18、jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE +17、混淆配置 +16、Android O的通知栏适配 +15、修复部分app网络卡的问题 +14、适配 android 8.0的dl_open(jni加载) +13、修复华为emui8.0的一个bug +12、完善定位 +11、设置手机信息,imei伪装算法 +10、适配8.0某个功能(主要app:whatsapp) +9、修复内部微信等应用,无法更新图片,视频 +8、demo增加安装监听,自动升级克隆模式的应用 +7、7.0的file provider适配 +6、增加了定位代码 +5、代码进行了架构优化 +4、与开源版不同的特征 +3、解决了微信被封的一些问题 +2、修复了部分机型兼容性 +1、修复了12个小BUG 已支持的加固(不断更新) From 5abc319f8d20c16d6c2d9464481abd9c294a4398 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Wed, 4 Apr 2018 19:33:44 +0800 Subject: [PATCH 057/334] CHINESE.md --- CHINESE.md | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 3043b689c..c944893bd 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,51 +27,51 @@ Q Q:10890
4月4日最新商业版更新: -1、修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。 -2、增加应用的保活机制,双开APP更不易被杀死。 -3、优化虚拟引擎启动性能。 -4、兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。 +1、修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。
+2、增加应用的保活机制,双开APP更不易被杀死。
+3、优化虚拟引擎启动性能。
+4、兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。
商业版代码历史更新: -38、修复某些rom下,快捷方式图标不正确 -37、兼容以前组件StubFileProvider -36、适配部分新ROM的虚拟IMEI -35、改善进程初始化代码,增加稳定性 -34、添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关 -33、适配关联google play游戏,支持游戏使用google登录 -32、适配android O的google service框架 -31、适配android O 快捷方式 -30、适配耳机模式 -29、某些rom对intent的大小限制,demo添加缩放快捷方式图标代码 -28、修复多开情况下一个bug -27、修复某些情况下MediaController的bug -26、修复4.1.2的StubFileProvider报错 -25、分享的uri处理 -24、修复跨app调用Activity的回调 -23、前台服务的通知栏拦截开关 -22、附带doc -21、完善VA内部的intent的CHOOSE回调 -20、Android O的通知栏适配2 -19、ipc框架优化, 提高判断binder的存活准确性 -18、jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE -17、混淆配置 -16、Android O的通知栏适配 -15、修复部分app网络卡的问题 -14、适配 android 8.0的dl_open(jni加载) -13、修复华为emui8.0的一个bug -12、完善定位 -11、设置手机信息,imei伪装算法 -10、适配8.0某个功能(主要app:whatsapp) -9、修复内部微信等应用,无法更新图片,视频 -8、demo增加安装监听,自动升级克隆模式的应用 -7、7.0的file provider适配 -6、增加了定位代码 -5、代码进行了架构优化 -4、与开源版不同的特征 -3、解决了微信被封的一些问题 -2、修复了部分机型兼容性 -1、修复了12个小BUG +38、修复某些rom下,快捷方式图标不正确
+37、兼容以前组件StubFileProvider
+36、适配部分新ROM的虚拟IMEI
+35、改善进程初始化代码,增加稳定性
+34、添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关
+33、适配关联google play游戏,支持游戏使用google登录
+32、适配android O的google service框架
+31、适配android O 快捷方式
+30、适配耳机模式
+29、某些rom对intent的大小限制,demo添加缩放快捷方式图标代码
+28、修复多开情况下一个bug
+27、修复某些情况下MediaController的bug
+26、修复4.1.2的StubFileProvider报错
+25、分享的uri处理
+24、修复跨app调用Activity的回调
+23、前台服务的通知栏拦截开关
+22、附带doc
+21、完善VA内部的intent的CHOOSE回调
+20、Android O的通知栏适配2
+19、ipc框架优化, 提高判断binder的存活准确性
+18、jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE
+17、混淆配置
+16、Android O的通知栏适配
+15、修复部分app网络卡的问题
+14、适配 android 8.0的dl_open(jni加载)
+13、修复华为emui8.0的一个bug
+12、完善定位
+11、设置手机信息,imei伪装算法
+10、适配8.0某个功能(主要app:whatsapp)
+9、修复内部微信等应用,无法更新图片,视频
+8、demo增加安装监听,自动升级克隆模式的应用
+7、7.0的file provider适配
+6、增加了定位代码
+5、代码进行了架构优化
+4、与开源版不同的特征
+3、解决了微信被封的一些问题
+2、修复了部分机型兼容性
+1、修复了12个小BUG
已支持的加固(不断更新) From e60c3caf2b5310c7bb7d78e9656fbbbc83758bfa Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Mon, 9 Apr 2018 10:40:02 +0800 Subject: [PATCH 058/334] CHINESE.md --- CHINESE.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index c944893bd..34d60181e 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -10,7 +10,7 @@ VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间 运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 -VA目前被广泛应用于双开/多开、应用市场、模拟定位、一键改机、隐私保护、游戏修改、自动化测试、无感知热更新等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能--------这都取决于您的想象力。 +VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP云加载、移动办公安全、军队政府保密、手机模拟信息、隐私保护、脚本自动化、自动化测试、游戏手柄免激活等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能--------这都取决于您的想象力。 申明 --- @@ -24,6 +24,10 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+4月9日最新商业版更新: + +1、解决微信数据库崩溃问题 +2、修复部分4.4设备崩溃问题 4月4日最新商业版更新: From a2332efeacad97a8b50c820c2eca1a5bfbb7110c Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Mon, 9 Apr 2018 10:48:46 +0800 Subject: [PATCH 059/334] CHINESE.md --- CHINESE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 34d60181e..2b6c8b776 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -26,8 +26,8 @@ Q Q:10890
4月9日最新商业版更新: -1、解决微信数据库崩溃问题 -2、修复部分4.4设备崩溃问题 +1、解决微信数据库崩溃问题
+2、修复部分4.4设备崩溃问题
4月4日最新商业版更新: From 68447dc13be54092d1cbf39a54b2e6b834c484c0 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Tue, 10 Apr 2018 11:33:19 +0800 Subject: [PATCH 060/334] CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 2b6c8b776..8a07c2b6e 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,7 +24,7 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
-4月9日最新商业版更新: +4月10日最新商业版更新: 1、解决微信数据库崩溃问题
2、修复部分4.4设备崩溃问题
From 43d0102103e75fd7b7c95c45775d6668144845f4 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Fri, 13 Apr 2018 10:36:33 +0800 Subject: [PATCH 061/334] CHINESE.md --- CHINESE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 8a07c2b6e..cb86882ea 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,6 +24,11 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+4月13日最新商业版更新: + +1、提高稳定性(修复微信登录闪退)
+ + 4月10日最新商业版更新: 1、解决微信数据库崩溃问题
From c7d5a8c45999894f6330c66134fc03f2d88a3d77 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Wed, 18 Apr 2018 12:33:21 +0800 Subject: [PATCH 062/334] CHINESE.md --- CHINESE.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index cb86882ea..f66c68b63 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,6 +24,14 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+4月17日最新商业版更新: + +1、提高ART稳定性(支持派派)
+2、增加相机适配范围
+3、支持内部App在8.0下的快捷方式管理
+4、修复exec异常
+ + 4月13日最新商业版更新: 1、提高稳定性(修复微信登录闪退)
From 787d51d9fadcb58c7929c74eac49cbac514588a3 Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Wed, 18 Apr 2018 12:39:13 +0800 Subject: [PATCH 063/334] Update CHINESE.md --- CHINESE.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index f66c68b63..520e7a993 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,33 +24,26 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
-4月17日最新商业版更新: - -1、提高ART稳定性(支持派派)
+4月17日最新商业版更新:
+1、提高ART稳定性
2、增加相机适配范围
3、支持内部App在8.0下的快捷方式管理
4、修复exec异常
- -4月13日最新商业版更新: - +4月13日最新商业版更新:
1、提高稳定性(修复微信登录闪退)
- -4月10日最新商业版更新: - +4月10日最新商业版更新:
1、解决微信数据库崩溃问题
2、修复部分4.4设备崩溃问题
-4月4日最新商业版更新: - +4月4日最新商业版更新:
1、修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。
2、增加应用的保活机制,双开APP更不易被杀死。
3、优化虚拟引擎启动性能。
4、兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。
-商业版代码历史更新: - +商业版代码历史更新:
38、修复某些rom下,快捷方式图标不正确
37、兼容以前组件StubFileProvider
36、适配部分新ROM的虚拟IMEI
From d7a817bc3ca4cfa193d5014fd17189248bca8e4f Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Fri, 20 Apr 2018 11:45:37 +0800 Subject: [PATCH 064/334] CHINESE.md --- CHINESE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index f66c68b63..cf3f1f3be 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,6 +24,10 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+4月20日最新商业版更新:
+1、提高对系统自带的app组件兼容性,更好兼容chrome webview,google service。
+ + 4月17日最新商业版更新: 1、提高ART稳定性(支持派派)
From 6e0395cf27a54c0fc9b84e1a6ca8b9cb4d40f6e6 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Wed, 25 Apr 2018 09:12:43 +0800 Subject: [PATCH 065/334] CHINESE.md --- CHINESE.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index a02497443..fdba1f379 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,10 +24,19 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+4月25日最新商业版更新:
+1、权限分类注释,标注可删除权限。
+2、增加双开模式的app跟随外部升级的开关。
+3、提高app的jni兼容性。
+4、提高对app集成其他插件框架的兼容性。
+5、增加设置接口,根据包名进行设置。
+6、增加Uri的适配范围,支持通过Uri分享和查看文件。
+7、修复一个在三星8.0的问题。
+ + 4月20日最新商业版更新:
1、提高对系统自带的app组件兼容性,更好兼容chrome webview,google service。
- 4月17日最新商业版更新:
1、提高ART稳定性
2、增加相机适配范围
From dc49a44b0258548801dc820b0839ded55966816a Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Fri, 27 Apr 2018 14:36:32 +0800 Subject: [PATCH 066/334] CHINESE.md --- CHINESE.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index fdba1f379..ac8f77392 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,6 +24,13 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+ +4月27日最新商业版更新:
+1、功能改动:google自动安装改为手动安装,避免第一次启动时间过久br/> +2、可以禁止访问外部某个ContentProvider
+3、适配华为桌面图标数量
+ + 4月25日最新商业版更新:
1、权限分类注释,标注可删除权限。
2、增加双开模式的app跟随外部升级的开关。
From 784ed0dfa4c54c6f1e3ef7f1aa07301b6218e484 Mon Sep 17 00:00:00 2001 From: kenan <247321453@qq.com> Date: Fri, 27 Apr 2018 17:00:52 +0800 Subject: [PATCH 067/334] CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index ac8f77392..fa83f10c5 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -26,7 +26,7 @@ Q Q:10890
4月27日最新商业版更新:
-1、功能改动:google自动安装改为手动安装,避免第一次启动时间过久br/> +1、功能改动:google自动安装改为手动安装,避免第一次启动时间过久
2、可以禁止访问外部某个ContentProvider
3、适配华为桌面图标数量
From 9f8fd6d0cc4a50e62420bbe199a89758bb64b928 Mon Sep 17 00:00:00 2001 From: kenan Date: Tue, 8 May 2018 20:41:07 +0800 Subject: [PATCH 068/334] CHINESE.md --- CHINESE.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index fa83f10c5..4649ec504 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,13 +24,18 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+5月8日最新商业版更新:
+1、修复ipc框架一个参数传递问题(IPCMethod这个类必须更新)
+2、补全7.0通知栏的hook
+3、修正8.0动态快捷菜单的hook
+4、SettingHandler新增一个适配接口,主要适配各种游戏
+ 4月27日最新商业版更新:
1、功能改动:google自动安装改为手动安装,避免第一次启动时间过久
2、可以禁止访问外部某个ContentProvider
3、适配华为桌面图标数量
- 4月25日最新商业版更新:
1、权限分类注释,标注可删除权限。
2、增加双开模式的app跟随外部升级的开关。
From 295ddc272207629c6726f511b411ca60bc7e62bd Mon Sep 17 00:00:00 2001 From: liuqiang Date: Tue, 15 May 2018 17:56:53 +0800 Subject: [PATCH 069/334] =?UTF-8?q?=E4=BF=AE=E5=A4=8Djobservice=20?= =?UTF-8?q?=E7=9A=84=E4=B8=80=E4=B8=AAbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/lody/virtual/server/BinderProvider.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java index a3bd51306..76dc4a546 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/BinderProvider.java @@ -22,6 +22,7 @@ import com.lody.virtual.server.interfaces.IActivityManager; import com.lody.virtual.server.interfaces.IAppManager; import com.lody.virtual.server.interfaces.IDeviceInfoManager; +import com.lody.virtual.server.interfaces.IJobService; import com.lody.virtual.server.interfaces.INotificationManager; import com.lody.virtual.server.interfaces.IPackageManager; import com.lody.virtual.server.interfaces.IServiceFetcher; @@ -61,7 +62,7 @@ public boolean onCreate() { IPCBus.register(IAppManager.class, VAppManagerService.get()); BroadcastSystem.attach(VActivityManagerService.get(), VAppManagerService.get()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - IPCBus.register(IJobScheduler.class, VJobSchedulerService.get()); + IPCBus.register(IJobService.class, VJobSchedulerService.get()); } VNotificationManagerService.systemReady(context); IPCBus.register(INotificationManager.class, VNotificationManagerService.get()); From 0d7a98c23c1005a1f3cfb470548cc0f2ec1c58b9 Mon Sep 17 00:00:00 2001 From: liuqiang Date: Tue, 15 May 2018 19:10:56 +0800 Subject: [PATCH 070/334] =?UTF-8?q?=E9=80=82=E9=85=8DAndroid=208.0=20JobIn?= =?UTF-8?q?tentService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VirtualApp/app/build.gradle | 2 +- VirtualApp/lib/build.gradle | 2 +- .../hook/proxies/job/JobServiceStub.java | 191 +++++++++++------- .../virtual/client/ipc/VJobScheduler.java | 22 ++ .../com/lody/virtual/client/stub/StubJob.java | 3 + .../virtual/helper/utils/ComponentUtils.java | 48 +++++ .../server/interfaces/IJobService.java | 5 + .../server/job/VJobSchedulerService.java | 46 +++++ .../mirror/android/app/job/JobWorkItem.java | 21 ++ 9 files changed, 268 insertions(+), 72 deletions(-) create mode 100644 VirtualApp/lib/src/main/java/mirror/android/app/job/JobWorkItem.java diff --git a/VirtualApp/app/build.gradle b/VirtualApp/app/build.gradle index d81390460..6fee2f9fe 100644 --- a/VirtualApp/app/build.gradle +++ b/VirtualApp/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 25 + compileSdkVersion 26 buildToolsVersion '26.0.2' defaultConfig { applicationId "io.virtualapp" diff --git a/VirtualApp/lib/build.gradle b/VirtualApp/lib/build.gradle index 740456fd6..6008db59a 100644 --- a/VirtualApp/lib/build.gradle +++ b/VirtualApp/lib/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 24 + compileSdkVersion 26 buildToolsVersion '26.0.2' defaultConfig { diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/job/JobServiceStub.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/job/JobServiceStub.java index 2682c4032..8b665938a 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/job/JobServiceStub.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/job/JobServiceStub.java @@ -3,91 +3,142 @@ import android.annotation.TargetApi; import android.app.job.JobInfo; import android.content.Context; +import android.content.Intent; import android.os.Build; +import android.os.Build.VERSION; import com.lody.virtual.client.hook.base.MethodProxy; import com.lody.virtual.client.hook.base.BinderInvocationProxy; import com.lody.virtual.client.ipc.VJobScheduler; +import com.lody.virtual.helper.utils.ComponentUtils; import java.lang.reflect.Method; import mirror.android.app.job.IJobScheduler; +import mirror.android.app.job.JobWorkItem; /** * @author Lody - * * @see android.app.job.JobScheduler */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class JobServiceStub extends BinderInvocationProxy { - public JobServiceStub() { - super(IJobScheduler.Stub.asInterface, Context.JOB_SCHEDULER_SERVICE); - } - - @Override - protected void onBindMethods() { - super.onBindMethods(); - addMethodProxy(new schedule()); - addMethodProxy(new getAllPendingJobs()); - addMethodProxy(new cancelAll()); - addMethodProxy(new cancel()); - } - - - private class schedule extends MethodProxy { - - @Override - public String getMethodName() { - return "schedule"; - } - - @Override - public Object call(Object who, Method method, Object... args) throws Throwable { - JobInfo jobInfo = (JobInfo) args[0]; - return VJobScheduler.get().schedule(jobInfo); - } - } - - private class getAllPendingJobs extends MethodProxy { - - @Override - public String getMethodName() { - return "getAllPendingJobs"; - } - - @Override - public Object call(Object who, Method method, Object... args) throws Throwable { - return VJobScheduler.get().getAllPendingJobs(); - } - } - - private class cancelAll extends MethodProxy { - - @Override - public String getMethodName() { - return "cancelAll"; - } - - @Override - public Object call(Object who, Method method, Object... args) throws Throwable { - VJobScheduler.get().cancelAll(); - return 0; - } - } - - private class cancel extends MethodProxy { - - @Override - public String getMethodName() { - return "cancel"; - } - - @Override - public Object call(Object who, Method method, Object... args) throws Throwable { - int jobId = (int) args[0]; - VJobScheduler.get().cancel(jobId); - return 0; - } - } + public JobServiceStub() { + super(IJobScheduler.Stub.asInterface, Context.JOB_SCHEDULER_SERVICE); + } + + @Override + protected void onBindMethods() { + super.onBindMethods(); + addMethodProxy(new schedule()); + addMethodProxy(new getAllPendingJobs()); + addMethodProxy(new cancelAll()); + addMethodProxy(new cancel()); + + if (VERSION.SDK_INT >= 24) { + addMethodProxy(new getPendingJob()); + } + if (VERSION.SDK_INT >= 26) { + addMethodProxy(new enqueue()); + } + } + + + private class schedule extends MethodProxy { + + @Override + public String getMethodName() { + return "schedule"; + } + + @Override + public Object call(Object who, Method method, Object... args) throws Throwable { + JobInfo jobInfo = (JobInfo) args[0]; + return VJobScheduler.get().schedule(jobInfo); + } + } + + private class getAllPendingJobs extends MethodProxy { + + @Override + public String getMethodName() { + return "getAllPendingJobs"; + } + + @Override + public Object call(Object who, Method method, Object... args) throws Throwable { + return VJobScheduler.get().getAllPendingJobs(); + } + } + + private class cancelAll extends MethodProxy { + + @Override + public String getMethodName() { + return "cancelAll"; + } + + @Override + public Object call(Object who, Method method, Object... args) throws Throwable { + VJobScheduler.get().cancelAll(); + return 0; + } + } + + private class cancel extends MethodProxy { + + @Override + public String getMethodName() { + return "cancel"; + } + + @Override + public Object call(Object who, Method method, Object... args) throws Throwable { + int jobId = (int) args[0]; + VJobScheduler.get().cancel(jobId); + return 0; + } + } + + private class getPendingJob extends MethodProxy { + private getPendingJob() { + } + + public Object call(Object who, Method method, Object... args) throws Throwable { + return VJobScheduler.get().getPendingJob((Integer) args[0]); + } + + public String getMethodName() { + return "getPendingJob"; + } + } + + private class enqueue extends MethodProxy { + private enqueue() { + } + + public Object call(Object who, Method method, Object... args) throws Throwable { + return VJobScheduler.get().enqueue( + (JobInfo) args[0], + JobServiceStub.this.redirect(args[1], MethodProxy.getAppPkg()) + ); + } + + public String getMethodName() { + return "enqueue"; + } + } + + private Object redirect(Object item, String pkg) { + if (item == null) { + return null; + } + Intent redirectIntentSender = ComponentUtils.redirectIntentSender(4, pkg, (Intent) JobWorkItem.getIntent.call(item, new Object[0]), null); + Object newInstance = JobWorkItem.ctor.newInstance(redirectIntentSender); + JobWorkItem.mWorkId.set(newInstance, JobWorkItem.mWorkId.get(item)); + JobWorkItem.mGrants.set(newInstance, JobWorkItem.mGrants.get(item)); + JobWorkItem.mDeliveryCount.set(newInstance, JobWorkItem.mDeliveryCount.get(item)); + return newInstance; + } } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java index a0b0de9e0..6d89e8506 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/ipc/VJobScheduler.java @@ -1,6 +1,7 @@ package com.lody.virtual.client.ipc; import android.app.job.JobInfo; +import android.os.Parcelable; import android.os.RemoteException; import com.lody.virtual.client.env.VirtualRuntime; @@ -58,4 +59,25 @@ public void cancel(int jobId) { e.printStackTrace(); } } + + + public JobInfo getPendingJob(int jobId) { + try { + return getService().getPendingJob(jobId); + } catch (RemoteException e) { + return (JobInfo) VirtualRuntime.crash(e); + } + } + + + public int enqueue(JobInfo job, Object workItem) { + if (workItem == null) { + return -1; + } + try { + return getService().enqueue(job, (Parcelable) workItem); + } catch (RemoteException e) { + return (Integer) VirtualRuntime.crash(e); + } + } } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/StubJob.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/StubJob.java index 18d87075d..113e054eb 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/StubJob.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/StubJob.java @@ -12,6 +12,7 @@ import android.os.Build; import android.os.IBinder; import android.os.RemoteException; +import android.util.Log; import com.lody.virtual.client.core.InvocationStubManager; import com.lody.virtual.client.hook.proxies.am.ActivityManagerStub; @@ -109,6 +110,8 @@ public void onCreate() { super.onCreate(); InvocationStubManager.getInstance().checkEnv(ActivityManagerStub.class); mScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE); + + Log.d("Q_M", "StubJob-->onCreate"); } @Override diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/utils/ComponentUtils.java b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/utils/ComponentUtils.java index c6007143f..91de7c8f2 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/helper/utils/ComponentUtils.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/helper/utils/ComponentUtils.java @@ -9,7 +9,15 @@ import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.env.SpecialComponentList; import com.lody.virtual.GmsSupport; +import com.lody.virtual.client.ipc.VActivityManager; +import com.lody.virtual.client.stub.StubPendingActivity; +import com.lody.virtual.client.stub.StubPendingReceiver; +import com.lody.virtual.client.stub.StubPendingService; import com.lody.virtual.helper.compat.ObjectsCompat; +import com.lody.virtual.os.VUserHandle; + +import android.os.IBinder; +import android.os.Parcelable; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; @@ -127,4 +135,44 @@ public static Intent redirectBroadcastIntent(Intent intent, int userId) { } return newIntent; } + + + public static Intent redirectIntentSender(int type, String creator, Intent intent, IBinder iBinder) { + Intent cloneFilter = intent.cloneFilter(); + switch (type) { + case 1: + cloneFilter.setClass(VirtualCore.get().getContext(), StubPendingReceiver.class); + break; + case 2: + if (VirtualCore.get().resolveActivityInfo(intent, VUserHandle.myUserId()) != null) { + cloneFilter.setClass(VirtualCore.get().getContext(), StubPendingActivity.class); + cloneFilter.setFlags(intent.getFlags()); + if (iBinder != null) { + try { + Parcelable activityForToken = VActivityManager.get().getActivityForToken(iBinder); + if (activityForToken != null) { + cloneFilter.putExtra("_VA_|_caller_", activityForToken); + break; + } + } catch (Throwable th) { + break; + } + } + } + break; + case 4: + if (VirtualCore.get().resolveServiceInfo(intent, VUserHandle.myUserId()) != null) { + cloneFilter.setClass(VirtualCore.get().getContext(), StubPendingService.class); + break; + } + break; + default: + return null; + } + cloneFilter.putExtra("_VA_|_user_id_", VUserHandle.myUserId()); + cloneFilter.putExtra("_VA_|_intent_", intent); + cloneFilter.putExtra("_VA_|_creator_", creator); + cloneFilter.putExtra("_VA_|_from_inner_", true); + return cloneFilter; + } } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java index 36c08a5bc..37e8d4f83 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/interfaces/IJobService.java @@ -1,6 +1,7 @@ package com.lody.virtual.server.interfaces; import android.app.job.JobInfo; +import android.os.Parcelable; import android.os.RemoteException; import java.util.List; @@ -17,4 +18,8 @@ public interface IJobService { void cancelAll() throws RemoteException; List getAllPendingJobs() throws RemoteException; + + int enqueue(JobInfo jobInfo, Parcelable parcelable) throws RemoteException; + + JobInfo getPendingJob(int i) throws RemoteException; } diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java index 7abb6faa2..9b4a7ce59 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/job/VJobSchedulerService.java @@ -3,6 +3,7 @@ import android.annotation.TargetApi; import android.app.job.JobInfo; import android.app.job.JobScheduler; +import android.app.job.JobWorkItem; import android.content.ComponentName; import android.content.Context; import android.os.Build; @@ -10,6 +11,7 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.text.TextUtils; +import android.util.Log; import com.lody.virtual.client.core.VirtualCore; import com.lody.virtual.client.ipc.VJobScheduler; @@ -27,6 +29,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; /** @@ -344,4 +347,47 @@ public Map.Entry findJobByVirtualJobId(int virtualJobId) { } } + @TargetApi(24) + public JobInfo getPendingJob(int jobId) { + int callingUid = VBinder.getCallingUid(); + JobInfo jobInfo = null; + synchronized (this.mJobStore) { + for (Entry key : this.mJobStore.entrySet()) { + JobId jobId2 = (JobId) key.getKey(); + if (jobId2.vuid == callingUid && jobId2.clientJobId == jobId) { + jobInfo = this.mScheduler.getPendingJob(jobId2.clientJobId); + break; + } + } + } + return jobInfo; + } + + @TargetApi(26) + public int enqueue(JobInfo job, Parcelable workItem) { + if (!(workItem instanceof JobWorkItem)) { + Log.d("Q_M","!(workItem instanceof JobWorkItem)"); + return -1; + } + Log.d("Q_M","(workItem instanceof JobWorkItem)"); + int callingUid = VBinder.getCallingUid(); + int id = job.getId(); + ComponentName service = job.getService(); + JobId jobId = new JobId(callingUid, service.getPackageName(), id); + JobConfig jobConfig = (JobConfig) this.mJobStore.get(jobId); + if (jobConfig == null) { + int i = this.mGlobalJobId; + this.mGlobalJobId = i + 1; + jobConfig = new JobConfig(i, service.getClassName(), job.getExtras()); + this.mJobStore.put(jobId, jobConfig); + } else { + jobConfig.serviceName = service.getClassName(); + jobConfig.extras = job.getExtras(); + } + saveJobs(); + mirror.android.app.job.JobInfo.jobId.set(job, jobConfig.virtualJobId); + mirror.android.app.job.JobInfo.service.set(job, this.mJobProxyComponent); + return this.mScheduler.enqueue(job, (JobWorkItem) workItem); + } + } diff --git a/VirtualApp/lib/src/main/java/mirror/android/app/job/JobWorkItem.java b/VirtualApp/lib/src/main/java/mirror/android/app/job/JobWorkItem.java new file mode 100644 index 000000000..c3f8ec52d --- /dev/null +++ b/VirtualApp/lib/src/main/java/mirror/android/app/job/JobWorkItem.java @@ -0,0 +1,21 @@ +package mirror.android.app.job; + +import android.annotation.TargetApi; +import android.content.Intent; +import mirror.MethodParams; +import mirror.RefClass; +import mirror.RefConstructor; +import mirror.RefInt; +import mirror.RefMethod; +import mirror.RefObject; + +@TargetApi(26) +public class JobWorkItem { + public static Class TYPE = RefClass.load(JobWorkItem.class, android.app.job.JobWorkItem.class); + @MethodParams({Intent.class}) + public static RefConstructor ctor; + public static RefMethod getIntent; + public static RefInt mDeliveryCount; + public static RefObject mGrants; + public static RefInt mWorkId; +} \ No newline at end of file From bf4041b33d668bf16a0d43cee39e9d0af639b9ec Mon Sep 17 00:00:00 2001 From: liuqiang Date: Wed, 16 May 2018 11:40:59 +0800 Subject: [PATCH 071/334] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 74 ++++++------------------------------------------------- 1 file changed, 7 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 24a891a42..26738e902 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,16 @@ -[![VA banner](https://raw.githubusercontent.com/asLody/VirtualApp/master/Logo.png)](https://github.com/asLody/VirtualApp) +[![Build Status](https://travis-ci.org/android-hacker/VirtualXposed.svg?branch=exposed)](https://travis-ci.org/android-hacker/VirtualXposed) -[中国人猛戳这里](CHINESE.md "中文") - -About +简介 ----- -**VirtualApp** is an open platform for Android that allows you to create a `Virtual Space`, -you can install and run apk inside. Beyond that, VirtualApp is also a `Plugin Framework`, -the plugins running on VirtualApp does not require any constraints. -VirtualApp does **not** require root, it is running on the `local process`. +本项目是在[VirtualApp](https://github.com/asLody/VirtualApp) 的基础上再次开发的,适配了一些在使用过程中出现的bug。 -NOTICE +警告 ------- -**This project has been authorized by the business.** - -**You are not allowed to modify the app module and put to the software market, if you do that, The consequences you know :)** - -**VirtualApp is not free, If you need to use the lib code, please send email to me :)** +本项目使用的 VirtualApp 不允许用于商业用途,如果有这个需求,请联系 Lody (imlody@foxmail.com)。 -Background +使用 ---------- -VirtualApp was born in early 2015, Originally, it is just a simple plugin framework, -But as time goes on, -the compatibility of it is getting better and better. -in the end, it evolved into a `Virtual Container`. - - -Get started ------------ -If you use latest android studio (version 2.0 or above), please disable `Instant Run`. -Open `Setting | Build,Exception,Deployment`, and disable `Enable Instant Run to hot swap...` - -**Goto your Application and insert the following code:** -```java - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - try { - VirtualCore.get().startup(base); - } catch (Throwable e) { - e.printStackTrace(); - } - } -``` - -**Install a virtual App:** -```java - VirtualCore.get().installPackage({APK PATH}, flags); - -``` - -**Launch a virtual App:** -```java - //VirtualApp support multi-user-mode which can run multiple instances of a same app. - //if you don't need this feature, just set `{userId}` to 0. - Intent intent = VirtualCore.get().getLaunchIntent({PackageName}, {userId}); - VActivityManager.get().startActivity(intent, {userId}); -``` - -**Uninstall a virtual App:** -```java - VirtualCore.get().uninstallPackage({PackageName}); -``` - -More details, please read the source code of demo app, :-) - -Documentation -------------- - -VirtualApp currently has **no documentation**, If you are interested in VirtualApp, please send email to me. +[猛戳这里](CHINESE.md "中文") -Contact us ------------- - zl@aluohe.com From 16ae534c130aff635011d4f3d9687a11090038b5 Mon Sep 17 00:00:00 2001 From: liuqiang Date: Wed, 16 May 2018 11:51:57 +0800 Subject: [PATCH 072/334] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 26738e902..5d095740f 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,50 @@ 警告 ------- -本项目使用的 VirtualApp 不允许用于商业用途,如果有这个需求,请联系 Lody (imlody@foxmail.com)。 +本项目使用的 VirtualApp 不允许用于商业用途,如果有这个需求,请联系 Lody (zl@aluohe.com)。 使用 ---------- [猛戳这里](CHINESE.md "中文") +使用说明 +---------- + +**前往你的Application并添加如下代码:** + +```java + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + try { + VirtualCore.getCore().startup(base); + } catch (Throwable e) { + e.printStackTrace(); + } + } +``` + +**安装App:** + +```java + VirtualCore.getCore().installApp({APK PATH}, flags); +``` + +**启动App:** + +```java + VirtualCore.getCore().launchApp({PackageName}); +``` + +**移除App:** + +```java + VirtualCore.getCore().uninstallApp({PackageName}); +``` + +**该App的基本信息:** +```java + VirtualCore.getCore().findApp({PackageName}); +``` From d13bec7116acceafb14a7a3685d15225de2ac4af Mon Sep 17 00:00:00 2001 From: liuqiang Date: Wed, 16 May 2018 13:54:10 +0800 Subject: [PATCH 073/334] =?UTF-8?q?=E6=B7=BB=E5=8A=A0VA=E5=86=85=E9=83=A8i?= =?UTF-8?q?ntent=20choose=20=E7=9A=84=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../virtual/server/pm/VPackageManagerService.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java index 22970a456..cd7fbb6c0 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java @@ -31,6 +31,8 @@ import java.io.File; import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -411,9 +413,19 @@ private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, int f } private ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags, List query, int priority) { + + try { + Class clazz = Class.forName("com.virtual.helper.VALibHelper"); + Method method = clazz.getDeclaredMethod("findPreferredActivity", Intent.class, String.class, int.class, List.class, int.class); + return (ResolveInfo) method.invoke(null, intent, resolvedType, flags, query, priority); + } catch (Exception e) { + e.printStackTrace(); + } + return null; } + @Override public List queryIntentActivities(Intent intent, String resolvedType, int flags, int userId) { checkUserId(userId); From f9a21f32553357148e1a2fbcac38564708108570 Mon Sep 17 00:00:00 2001 From: liuqiang Date: Wed, 16 May 2018 19:12:43 +0800 Subject: [PATCH 074/334] =?UTF-8?q?=E4=BF=AE=E6=94=B9inten=20=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E8=A7=84=E5=88=99=EF=BC=8C=E4=BD=86=E4=B8=8D=E6=98=AF?= =?UTF-8?q?=E6=9C=80=E4=BC=98=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lody/virtual/server/pm/VPackageManagerService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java index cd7fbb6c0..1de66fdf0 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/server/pm/VPackageManagerService.java @@ -400,13 +400,16 @@ private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, int f // If we have saved a preference for a preferred activity for // this Intent, use that. + //从候选列表中查找一个最合适的,如果候选列表没有最合适的返回null + //然后从系统中查找合适的打开intent ResolveInfo ri = findPreferredActivity(intent, resolvedType, flags, query, r0.priority); //noinspection ConstantConditions if (ri != null) { return ri; } - return query.get(0); + + return null; } } return null; @@ -420,9 +423,10 @@ private ResolveInfo findPreferredActivity(Intent intent, String resolvedType, in return (ResolveInfo) method.invoke(null, intent, resolvedType, flags, query, priority); } catch (Exception e) { e.printStackTrace(); + return query.get(0); } - return null; +// return null; } From ae5bb716bdda6093f0cf4517494a9714785e0558 Mon Sep 17 00:00:00 2001 From: liuqiang Date: Tue, 22 May 2018 17:55:39 +0800 Subject: [PATCH 075/334] =?UTF-8?q?=E6=98=AF=E5=90=A6=E5=85=81=E8=AE=B8?= =?UTF-8?q?=E6=8F=92=E4=BB=B6=E5=BA=94=E7=94=A8=E7=9B=B4=E6=8E=A5=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=B3=BB=E7=BB=9F=E6=A1=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/hook/proxies/am/MethodProxies.java | 21 ++++++++++++++++++- .../lody/virtual/client/stub/VASettings.java | 10 +++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java index a6a415560..2ae83489f 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/hook/proxies/am/MethodProxies.java @@ -28,6 +28,7 @@ import android.os.IInterface; import android.os.RemoteException; import android.text.TextUtils; +import android.util.Log; import android.util.TypedValue; import com.lody.virtual.client.VClientImpl; @@ -79,6 +80,8 @@ import mirror.android.content.IIntentReceiverJB; import mirror.android.content.pm.UserInfo; +import static com.lody.virtual.client.stub.VASettings.INTERCEPT_BACK_HOME; + /** * @author Lody */ @@ -374,6 +377,9 @@ public String getMethodName() { @Override public Object call(Object who, Method method, Object... args) throws Throwable { + + Log.d("Q_M", "---->StartActivity 类"); + int intentIndex = ArrayUtils.indexOfObject(args, Intent.class, 1); if (intentIndex < 0) { return ActivityManagerCompat.START_INTENT_NOT_RESOLVED; @@ -433,9 +439,22 @@ public Object call(Object who, Method method, Object... args) throws Throwable { ActivityInfo activityInfo = VirtualCore.get().resolveActivityInfo(intent, userId); if (activityInfo == null) { VLog.e("VActivityManager", "Unable to resolve activityInfo : " + intent); + + Log.d("Q_M", "---->StartActivity who=" + who); + Log.d("Q_M", "---->StartActivity intent=" + intent); + Log.d("Q_M", "---->StartActivity resultTo=" + resultTo); + if (intent.getPackage() != null && isAppPkg(intent.getPackage())) { return ActivityManagerCompat.START_INTENT_NOT_RESOLVED; } + + if (INTERCEPT_BACK_HOME && Intent.ACTION_MAIN.equals(intent.getAction()) + && intent.getCategories().contains("android.intent.category.HOME") + && resultTo != null) { + VActivityManager.get().finishActivity(resultTo); + return 0; + } + return method.invoke(who, args); } int res = VActivityManager.get().startActivity(intent, activityInfo, resultTo, options, resultWho, requestCode, VUserHandle.myUserId()); @@ -481,7 +500,7 @@ private boolean handleInstallRequest(Intent intent) { } catch (RemoteException e) { e.printStackTrace(); } - } else if (SCHEME_CONTENT.equals(packageUri.getScheme())){ + } else if (SCHEME_CONTENT.equals(packageUri.getScheme())) { InputStream inputStream = null; OutputStream outputStream = null; File sharedFileCopy = new File(getHostContext().getCacheDir(), packageUri.getLastPathSegment()); diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/VASettings.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/VASettings.java index 8c662c38d..46bc8717e 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/VASettings.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/stub/VASettings.java @@ -20,6 +20,16 @@ public class VASettings { "com.google.android.gms" }; + /** + * 是否禁止插件应用直接调用返回桌面的 intent + *

+ * Intent home = new Intent(Intent.ACTION_MAIN); + * home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + * home.addCategory(Intent.CATEGORY_HOME); + * startActivity(home); + */ + public static boolean INTERCEPT_BACK_HOME = true; + /** * If enable, * App run in VA will allowed to create shortcut on your Desktop. From ca9dc82198e876b488a76ba492d163b47946cd19 Mon Sep 17 00:00:00 2001 From: kenan Date: Tue, 22 May 2018 19:17:10 +0800 Subject: [PATCH 076/334] CHINESE.md --- CHINESE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 4649ec504..129073dbb 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,6 +24,17 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+ +5月22日最新商业版更新:
+1、安全性更新,内部应用的文件权限控制
+2、提高内部app调用的兼容性,第三方登录,分享
+3、自动过滤没权限的外部ContentProvider
+4、增加功能:内部app的权限检查(默认关闭)
+5、机型模拟:Build类和build.prop
+6、提高对乐固加固的app兼容性
+7、适配三星wifimanager
+ + 5月8日最新商业版更新:
1、修复ipc框架一个参数传递问题(IPCMethod这个类必须更新)
2、补全7.0通知栏的hook
From 5dae2f98a73433a0d84df425ec42264c43013834 Mon Sep 17 00:00:00 2001 From: kenan Date: Fri, 25 May 2018 11:41:02 +0800 Subject: [PATCH 077/334] CHINESE.md --- CHINESE.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 129073dbb..9bebc33d6 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -25,6 +25,12 @@ Q Q:10890
商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+5月24日最新商业版更新:
+1、适配vivo一个自定义权限(后台弹窗)VA是把一个历史acitivty返回前台,vivo需要这个权限。
+2、如果没有蓝牙权限,返回默认值(海外用)
+3、修复uid权限检查问题
+ + 5月22日最新商业版更新:
1、安全性更新,内部应用的文件权限控制
2、提高内部app调用的兼容性,第三方登录,分享
@@ -34,7 +40,6 @@ Q Q:10890
6、提高对乐固加固的app兼容性
7、适配三星wifimanager
- 5月8日最新商业版更新:
1、修复ipc框架一个参数传递问题(IPCMethod这个类必须更新)
2、补全7.0通知栏的hook
From 050f2b79893508e16bd098c904adce608abcea86 Mon Sep 17 00:00:00 2001 From: kenan Date: Tue, 29 May 2018 15:41:20 +0800 Subject: [PATCH 078/334] CHINESE.md --- CHINESE.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 9bebc33d6..9810eb394 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,9 +14,11 @@ VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP 申明 --- -VirtualApp在2017年8月份正式公司化运作,当您需要将VirtualApp用于商业用途时,请联系QQ:10890 购买商业授权。您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传软件市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。
+VirtualApp是罗盒科技开发运营,罗盒科技在深圳及山东设有公司,于2015年至2018年陆续申请多项VirtualApp知识产权。当您需要将VirtualApp用于商业用途时,请购买商业授权。
-目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您所在公司节省大量开发完善时间,保障产品高效上线运营,让您有更多时间用于创新及盈利。获取VirtualApp商业授权后您将得到:商业版代码、说明接入文档、微信和QQ群技术支持。
+您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传应用市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。
+
+目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利。获取VirtualApp商业授权后您将得到:商业版代码、说明接入文档、微信和QQ群技术支持。

负责人:张总
手机:130-321-77777
From e6d3f5a44866a6aa48f6e5472d213b674dca1f0e Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Tue, 29 May 2018 16:54:58 +0800 Subject: [PATCH 079/334] Update CHINESE.md --- CHINESE.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 9810eb394..1e2f8f231 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,11 +14,10 @@ VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP 申明 --- -VirtualApp是罗盒科技开发运营,罗盒科技在深圳及山东设有公司,于2015年至2018年陆续申请多项VirtualApp知识产权。当您需要将VirtualApp用于商业用途时,请购买商业授权。 +  VirtualApp是罗盒科技开发运营,罗盒科技在深圳及山东设有公司,于2015年至2018年陆续申请多项VirtualApp知识产权。当您需要将VirtualApp用于商业用途时,请购买商业授权。
-您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传应用市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。
-
-目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利。获取VirtualApp商业授权后您将得到:商业版代码、说明接入文档、微信和QQ群技术支持。
+  您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传应用市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。
+  目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利。获取VirtualApp商业授权后您将得到:商业版代码、说明接入文档、微信和QQ群技术支持。

负责人:张总
手机:130-321-77777
From 2c593a59491473b76f93547b593590a7008a7f5e Mon Sep 17 00:00:00 2001 From: ke yongyu <247321453@qq.com> Date: Tue, 29 May 2018 16:56:36 +0800 Subject: [PATCH 080/334] Update CHINESE.md --- CHINESE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 1e2f8f231..360cde63f 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -14,9 +14,10 @@ VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP 申明 --- -  VirtualApp是罗盒科技开发运营,罗盒科技在深圳及山东设有公司,于2015年至2018年陆续申请多项VirtualApp知识产权。当您需要将VirtualApp用于商业用途时,请购买商业授权。 +  VirtualApp是罗盒科技开发运营,罗盒科技在深圳及山东设有公司,于2015年至2018年陆续申请多项VirtualApp知识产权。当您需要将VirtualApp用于商业用途时,请购买商业授权。

  您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传应用市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。
+
  目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利。获取VirtualApp商业授权后您将得到:商业版代码、说明接入文档、微信和QQ群技术支持。

负责人:张总
From 2782d1f1af35eba5d0041e2171550000233de344 Mon Sep 17 00:00:00 2001 From: Enyby Date: Mon, 4 Jun 2018 13:12:26 +0300 Subject: [PATCH 081/334] Failed exec any app See #497 --- VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp index 46f17b36a..d48debd21 100644 --- a/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp +++ b/VirtualApp/lib/src/main/jni/Foundation/IOUniformer.cpp @@ -550,7 +550,7 @@ HOOK_DEF(int, execve, const char *pathname, char *argv[], char *const envp[]) { * * We will support 64Bit to adopt it. */ - ALOGE("execve : %s", pathname); + // ALOGE("execve : %s", pathname); // any output can break exec. See bug: https://issuetracker.google.com/issues/109448553 int res; const char *redirect_path = relocate_path(pathname, &res); char *ld = getenv("LD_PRELOAD"); From abf726ec60918ec59d3b3673d0e45cbc13154b2d Mon Sep 17 00:00:00 2001 From: Enyby Date: Mon, 4 Jun 2018 13:15:13 +0300 Subject: [PATCH 082/334] Fix ThreadGroup is parent for self See #496 --- .../lib/src/main/java/com/lody/virtual/client/VClientImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java b/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java index e06c316b7..3d9bdffc3 100644 --- a/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java +++ b/VirtualApp/lib/src/main/java/com/lody/virtual/client/VClientImpl.java @@ -378,6 +378,7 @@ private void setupUncaughtHandler() { groups.add(newRoot); mirror.java.lang.ThreadGroup.groups.set(root, groups); for (ThreadGroup group : newGroups) { + if (group == newRoot) continue; mirror.java.lang.ThreadGroup.parent.set(group, newRoot); } } @@ -389,6 +390,7 @@ private void setupUncaughtHandler() { ThreadGroupN.groups.set(newRoot, newGroups); ThreadGroupN.groups.set(root, new ThreadGroup[]{newRoot}); for (Object group : newGroups) { + if (group == newRoot) continue; ThreadGroupN.parent.set(group, newRoot); } ThreadGroupN.ngroups.set(root, 1); From 80422e6faa622c78cd6af3f70343748a79992614 Mon Sep 17 00:00:00 2001 From: kenan Date: Tue, 5 Jun 2018 10:09:48 +0800 Subject: [PATCH 083/334] resotre README.md --- README.md | 69 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 5d095740f..24a891a42 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,76 @@ -[![Build Status](https://travis-ci.org/android-hacker/VirtualXposed.svg?branch=exposed)](https://travis-ci.org/android-hacker/VirtualXposed) +[![VA banner](https://raw.githubusercontent.com/asLody/VirtualApp/master/Logo.png)](https://github.com/asLody/VirtualApp) -简介 +[中国人猛戳这里](CHINESE.md "中文") + +About ----- -本项目是在[VirtualApp](https://github.com/asLody/VirtualApp) 的基础上再次开发的,适配了一些在使用过程中出现的bug。 +**VirtualApp** is an open platform for Android that allows you to create a `Virtual Space`, +you can install and run apk inside. Beyond that, VirtualApp is also a `Plugin Framework`, +the plugins running on VirtualApp does not require any constraints. +VirtualApp does **not** require root, it is running on the `local process`. -警告 +NOTICE ------- -本项目使用的 VirtualApp 不允许用于商业用途,如果有这个需求,请联系 Lody (zl@aluohe.com)。 +**This project has been authorized by the business.** -使用 ----------- +**You are not allowed to modify the app module and put to the software market, if you do that, The consequences you know :)** -[猛戳这里](CHINESE.md "中文") +**VirtualApp is not free, If you need to use the lib code, please send email to me :)** -使用说明 +Background ---------- -**前往你的Application并添加如下代码:** +VirtualApp was born in early 2015, Originally, it is just a simple plugin framework, +But as time goes on, +the compatibility of it is getting better and better. +in the end, it evolved into a `Virtual Container`. + +Get started +----------- +If you use latest android studio (version 2.0 or above), please disable `Instant Run`. +Open `Setting | Build,Exception,Deployment`, and disable `Enable Instant Run to hot swap...` + +**Goto your Application and insert the following code:** ```java @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); try { - VirtualCore.getCore().startup(base); + VirtualCore.get().startup(base); } catch (Throwable e) { e.printStackTrace(); } } ``` -**安装App:** - +**Install a virtual App:** ```java - VirtualCore.getCore().installApp({APK PATH}, flags); + VirtualCore.get().installPackage({APK PATH}, flags); + ``` -**启动App:** - +**Launch a virtual App:** ```java - VirtualCore.getCore().launchApp({PackageName}); + //VirtualApp support multi-user-mode which can run multiple instances of a same app. + //if you don't need this feature, just set `{userId}` to 0. + Intent intent = VirtualCore.get().getLaunchIntent({PackageName}, {userId}); + VActivityManager.get().startActivity(intent, {userId}); ``` -**移除App:** - +**Uninstall a virtual App:** ```java - VirtualCore.getCore().uninstallApp({PackageName}); + VirtualCore.get().uninstallPackage({PackageName}); ``` -**该App的基本信息:** +More details, please read the source code of demo app, :-) -```java - VirtualCore.getCore().findApp({PackageName}); -``` +Documentation +------------- + +VirtualApp currently has **no documentation**, If you are interested in VirtualApp, please send email to me. + +Contact us +------------ + + zl@aluohe.com From ecedbdb5079905ef522a517f37e30d0cade31f47 Mon Sep 17 00:00:00 2001 From: kenan Date: Thu, 14 Jun 2018 15:08:44 +0800 Subject: [PATCH 084/334] VERSION --- CHINESE.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 360cde63f..e13cd0544 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,6 +27,27 @@ Q Q:10890
商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+6月14日最新商业版更新:
+1、64位支持还在开发阶段
+2、更新混淆配置app/proguard-rules.pro,必须加规则-dontshrink
+3、优化模拟机型,例如:模拟后,某些app不出现设备验证
+4、提高dex2oat兼容性
+5、优化模拟定位
+6、移除dlopen
+7、targetVersion可以改为26:支持targetVersion<23的app动态权限申请,支持targetVersion<24的文件Uri
+ + +6月8日最新商业版更新:
+1、为了支持64位模式,换回aidl
+2、去掉SettingHandler现在可以动态设置特殊规则,规则会存储,不需要重复设置
+3、增加2个native_setup
+4、提高jobService兼容性
+5、ShortcutService相关:关联VASettings.ENABLE_INNER_SHORTCUT
+6、为了稳定性和运行效率,去掉上个版本的蓝牙,wifi,不声明权限的适配。
+7、增加app启动异常的广播Constants.ACTION_PROCESS_ERROR
+8、修复少数游戏横屏判断问题
+9、demo增加机型模拟
+ 5月24日最新商业版更新:
1、适配vivo一个自定义权限(后台弹窗)VA是把一个历史acitivty返回前台,vivo需要这个权限。
2、如果没有蓝牙权限,返回默认值(海外用)
From 1fdc070f4be8be7272725807b60235beaf2a5717 Mon Sep 17 00:00:00 2001 From: kenan Date: Thu, 14 Jun 2018 15:27:39 +0800 Subject: [PATCH 085/334] CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index e13cd0544..f238cae6f 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -35,6 +35,7 @@ Q Q:10890
5、优化模拟定位
6、移除dlopen
7、targetVersion可以改为26:支持targetVersion<23的app动态权限申请,支持targetVersion<24的文件Uri
+8、installPackage改为默认异步形式
6月8日最新商业版更新:
From c34ed4d55cf5e9750958bce04874b72f4cc51075 Mon Sep 17 00:00:00 2001 From: kenan Date: Mon, 9 Jul 2018 19:48:25 +0800 Subject: [PATCH 086/334] CHINESE.md --- CHINESE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index f238cae6f..4a8437223 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -26,6 +26,15 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+7月6日最新商业版更新:
+1、优化hook库的兼容性,加回dlopen
+2、64位扩展包的so移到32位主包。(jni代码改动后,在Run之前,请先build一次)
+3、通知栏改动:适配8.1的通知渠道;移除应用时,移除应用的全部通知
+4、兼容部分app,需要设置android:largeHeap=true
+5、修复ffmpeg库的视频无法播放问题
+6、优化横竖屏切换
+7、降低通过Intent.ACTION_VIEW调用外部Activity限制。
+8、兼容MG SDK
6月14日最新商业版更新:
1、64位支持还在开发阶段
From b3e03a2231aef41443e47bb7bbf7396dae0674bd Mon Sep 17 00:00:00 2001 From: kenan Date: Mon, 16 Jul 2018 14:38:30 +0800 Subject: [PATCH 087/334] CHINESE.md --- CHINESE.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 4a8437223..62f8b1b54 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -26,6 +26,13 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+7月10日最新商业版更新:
+1、适配autofill服务,例如piexl系列
+2、完善64位的io hook
+目前已知问题:
+1、无法启动部分阿里加固过的app,例如:墨迹天气
+2、网易新闻的微博分享sdk调用不正常
+ 7月6日最新商业版更新:
1、优化hook库的兼容性,加回dlopen
2、64位扩展包的so移到32位主包。(jni代码改动后,在Run之前,请先build一次)
From e13b9661e4e9e98d326f88b32f49cfa1c513887d Mon Sep 17 00:00:00 2001 From: kenan Date: Mon, 23 Jul 2018 23:35:34 +0800 Subject: [PATCH 088/334] CHINESE.md --- CHINESE.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 62f8b1b54..293cd88e2 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -29,9 +29,6 @@ Q Q:10890
7月10日最新商业版更新:
1、适配autofill服务,例如piexl系列
2、完善64位的io hook
-目前已知问题:
-1、无法启动部分阿里加固过的app,例如:墨迹天气
-2、网易新闻的微博分享sdk调用不正常
7月6日最新商业版更新:
1、优化hook库的兼容性,加回dlopen
From 5cbbdb3ebeec3404c68e2a443fdcc36beb707bfa Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 8 Aug 2018 16:52:43 +0800 Subject: [PATCH 089/334] Update CHINESE.md --- CHINESE.md | 178 ++++++++++++++++++++++++----------------------------- 1 file changed, 81 insertions(+), 97 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 293cd88e2..78f2dcdfc 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -26,102 +26,86 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
-7月10日最新商业版更新:
-1、适配autofill服务,例如piexl系列
-2、完善64位的io hook
- -7月6日最新商业版更新:
-1、优化hook库的兼容性,加回dlopen
-2、64位扩展包的so移到32位主包。(jni代码改动后,在Run之前,请先build一次)
-3、通知栏改动:适配8.1的通知渠道;移除应用时,移除应用的全部通知
-4、兼容部分app,需要设置android:largeHeap=true
-5、修复ffmpeg库的视频无法播放问题
-6、优化横竖屏切换
-7、降低通过Intent.ACTION_VIEW调用外部Activity限制。
-8、兼容MG SDK
- -6月14日最新商业版更新:
-1、64位支持还在开发阶段
-2、更新混淆配置app/proguard-rules.pro,必须加规则-dontshrink
-3、优化模拟机型,例如:模拟后,某些app不出现设备验证
-4、提高dex2oat兼容性
-5、优化模拟定位
-6、移除dlopen
-7、targetVersion可以改为26:支持targetVersion<23的app动态权限申请,支持targetVersion<24的文件Uri
-8、installPackage改为默认异步形式
- - -6月8日最新商业版更新:
-1、为了支持64位模式,换回aidl
-2、去掉SettingHandler现在可以动态设置特殊规则,规则会存储,不需要重复设置
-3、增加2个native_setup
-4、提高jobService兼容性
-5、ShortcutService相关:关联VASettings.ENABLE_INNER_SHORTCUT
-6、为了稳定性和运行效率,去掉上个版本的蓝牙,wifi,不声明权限的适配。
-7、增加app启动异常的广播Constants.ACTION_PROCESS_ERROR
-8、修复少数游戏横屏判断问题
-9、demo增加机型模拟
- -5月24日最新商业版更新:
-1、适配vivo一个自定义权限(后台弹窗)VA是把一个历史acitivty返回前台,vivo需要这个权限。
-2、如果没有蓝牙权限,返回默认值(海外用)
-3、修复uid权限检查问题
- - -5月22日最新商业版更新:
-1、安全性更新,内部应用的文件权限控制
-2、提高内部app调用的兼容性,第三方登录,分享
-3、自动过滤没权限的外部ContentProvider
-4、增加功能:内部app的权限检查(默认关闭)
-5、机型模拟:Build类和build.prop
-6、提高对乐固加固的app兼容性
-7、适配三星wifimanager
- -5月8日最新商业版更新:
-1、修复ipc框架一个参数传递问题(IPCMethod这个类必须更新)
-2、补全7.0通知栏的hook
-3、修正8.0动态快捷菜单的hook
-4、SettingHandler新增一个适配接口,主要适配各种游戏
- - -4月27日最新商业版更新:
-1、功能改动:google自动安装改为手动安装,避免第一次启动时间过久
-2、可以禁止访问外部某个ContentProvider
-3、适配华为桌面图标数量
- -4月25日最新商业版更新:
-1、权限分类注释,标注可删除权限。
-2、增加双开模式的app跟随外部升级的开关。
-3、提高app的jni兼容性。
-4、提高对app集成其他插件框架的兼容性。
-5、增加设置接口,根据包名进行设置。
-6、增加Uri的适配范围,支持通过Uri分享和查看文件。
-7、修复一个在三星8.0的问题。
- - -4月20日最新商业版更新:
-1、提高对系统自带的app组件兼容性,更好兼容chrome webview,google service。
- -4月17日最新商业版更新:
-1、提高ART稳定性
-2、增加相机适配范围
-3、支持内部App在8.0下的快捷方式管理
-4、修复exec异常
- -4月13日最新商业版更新:
-1、提高稳定性(修复微信登录闪退)
- -4月10日最新商业版更新:
-1、解决微信数据库崩溃问题
-2、修复部分4.4设备崩溃问题
- -4月4日最新商业版更新:
-1、修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。
-2、增加应用的保活机制,双开APP更不易被杀死。
-3、优化虚拟引擎启动性能。
-4、兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。
- -商业版代码历史更新:
+8月6日最新商业版更新:
+1、修复三星系列应用的相互调用问题
+2、修复小米应用在非小米系统的账号问题
+3、修复分享/发送等第三方调用,返回页面不正常
+4、修复应用宝提示不能安装
+5、调用第三方app,对uri进行加密
+6、适配前刘海
+7、适配小米rom的hook
+8、适配努比亚录音问题
+9、内部悬浮窗权限控制
+9、优化自定义通知栏的处理
+10、修复Context的INCLUDE_CODE权限问题
+11、适配华为,oppo的角标
+12、修复百度视频的进程重启问题
+13、修复某些snapchat的无法启动问题
+
+2018年1月1日至7月31日历史更新:
+101、适配autofill服务,例如piexl系列
+100、完善64位的io hook
+99、优化hook库的兼容性,加回dlopen
+98、64位扩展包的so移到32位主包。(jni代码改动后,在Run之前,请先build一次)
+97、通知栏改动:适配8.1的通知渠道;移除应用时,移除应用的全部通知
+96、兼容部分app,需要设置android:largeHeap=true
+95、修复ffmpeg库的视频无法播放问题
+94、优化横竖屏切换
+93、降低通过Intent.ACTION_VIEW调用外部Activity限制。
+92、兼容MG SDK
+91、64位支持还在开发阶段
+90、更新混淆配置app/proguard-rules.pro,必须加规则-dontshrink
+89、优化模拟机型,例如:模拟后,某些app不出现设备验证
+88、提高dex2oat兼容性
+87、优化模拟定位
+86、移除dlopen
+85、targetVersion可以改为26:支持targetVersion<23的app动态权限申请,支持targetVersion<24的文件Uri
+84、installPackage改为默认异步形式
+83、为了支持64位模式,换回aidl
+82、去掉SettingHandler现在可以动态设置特殊规则,规则会存储,不需要重复设置
+81、增加2个native_setup
+80、提高jobService兼容性
+79、ShortcutService相关:关联VASettings.ENABLE_INNER_SHORTCUT
+78、为了稳定性和运行效率,去掉上个版本的蓝牙,wifi,不声明权限的适配。
+77、增加app启动异常的广播Constants.ACTION_PROCESS_ERROR
+76、修复少数游戏横屏判断问题
+75、demo增加机型模拟
+74、适配vivo一个自定义权限(后台弹窗)VA是把一个历史acitivty返回前台,vivo需要这个权限。
+73、如果没有蓝牙权限,返回默认值(海外用)
+72、修复uid权限检查问题
+71、安全性更新,内部应用的文件权限控制
+70、提高内部app调用的兼容性,第三方登录,分享
+69、自动过滤没权限的外部ContentProvider
+68、增加功能:内部app的权限检查(默认关闭)
+67、机型模拟:Build类和build.prop
+66、提高对乐固加固的app兼容性
+65、适配三星wifimanager
+64、修复ipc框架一个参数传递问题(IPCMethod这个类必须更新)
+63、补全7.0通知栏的hook
+62、修正8.0动态快捷菜单的hook
+61、SettingHandler新增一个适配接口,主要适配各种游戏
+60、功能改动:google自动安装改为手动安装,避免第一次启动时间过久
+59、可以禁止访问外部某个ContentProvider
+58、适配华为桌面图标数量
+57、权限分类注释,标注可删除权限。
+56、增加双开模式的app跟随外部升级的开关。
+55、提高app的jni兼容性。
+54、提高对app集成其他插件框架的兼容性。
+53、增加设置接口,根据包名进行设置。
+52、增加Uri的适配范围,支持通过Uri分享和查看文件。
+51、修复一个在三星8.0的问题。
+50、提高对系统自带的app组件兼容性,更好兼容chrome webview,google service。
+49、提高ART稳定性
+48、增加相机适配范围
+47、支持内部App在8.0下的快捷方式管理
+46、修复exec异常
+45、提高稳定性(修复微信登录闪退)
+44、解决微信数据库崩溃问题
+43、修复部分4.4设备崩溃问题
+42、修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。
+41、增加应用的保活机制,双开APP更不易被杀死。
+40、优化虚拟引擎启动性能。
+39、兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。
38、修复某些rom下,快捷方式图标不正确
37、兼容以前组件StubFileProvider
36、适配部分新ROM的虚拟IMEI
@@ -159,7 +143,7 @@ Q Q:10890
4、与开源版不同的特征
3、解决了微信被封的一些问题
2、修复了部分机型兼容性
-1、修复了12个小BUG
+1、修复了12个小BUG 已支持的加固(不断更新) From 7aa69088450717de299ad7006176341614af1b4a Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 19 Aug 2018 09:18:34 +0800 Subject: [PATCH 090/334] Update CHINESE.md --- CHINESE.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 78f2dcdfc..a3ef3f97a 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -24,7 +24,24 @@ VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP 手机:130-321-77777
Q Q:10890

-商业版代码保持每月1-2次以上频率持续更新,并对Android 8.0进行大量适配,保证了兼容性。
+商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+ +8月17日最新商业版更新:
+1、兼容最新Android 9.0(代号: pie) 及正式版之前发布的四个Preview版本
+2、兼容内置houdini的x86设备
+3、WindowPreview技术,使app启动与真实app达到一样的速度
+4、新的ActivityStack以提高app运行质量
+5、解决接入Atlas Framework的app运行异常的问题
+6、现在可以定义虚拟app返回桌面的具体行为
+7、现在双开模式下app随系统动态更新,不需要手动检查
+8、支持targetSdkVersion >= 26时仍可正常运行低版本的app
+9、兼容腾讯游戏管家的QDroid虚拟引擎 (beta)
+10、大量重构底层代码,大幅提升运行速度
+11、修复网易新闻分享到微博后无法取消的问题
+12、修复App自定义权限无法识别的问题
+13、修复墨迹天气app无法启动的问题
+13、修复部分政府app无法启动的问题
+14、API的变动详见代码
8月6日最新商业版更新:
1、修复三星系列应用的相互调用问题
From 5127ea09dd47106290ffadeae868e0579abd7633 Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 26 Aug 2018 18:46:13 +0800 Subject: [PATCH 091/334] Update CHINESE.md --- CHINESE.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index a3ef3f97a..4a864af19 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -2,9 +2,9 @@ 简介 --- -**VirtualApp**是一个**App虚拟化引擎**(简称`VA`)。 +**VirtualApp**是一个已经商业化的**App虚拟化引擎**(简称`VA`)。 -**VirtualApp已兼容Android 0(8.0)。** +**VirtualApp商业版已兼容Android P(9.0)和支持运行纯64位的App。** VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 @@ -26,6 +26,13 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+8月26日最新商业版更新:
+1、修复移动MM SDK无法启动的问题
+2、修复微信摇一摇的BUG
+3、修复中兴设备不稳定的BUG
+4、支持ARM64下的IO Redirect
+5、修复USE_OUTSIDE模式下外部app更新时,内部app没有更新的BUG
+ 8月17日最新商业版更新:
1、兼容最新Android 9.0(代号: pie) 及正式版之前发布的四个Preview版本
2、兼容内置houdini的x86设备
From e3bd66f959e81ba22808cb97df32e22a9b10158a Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 2 Sep 2018 19:32:05 +0800 Subject: [PATCH 092/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 4a864af19..4be7961e4 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -5,6 +5,7 @@ **VirtualApp**是一个已经商业化的**App虚拟化引擎**(简称`VA`)。 **VirtualApp商业版已兼容Android P(9.0)和支持运行纯64位的App。** +**VirtualApp商业版现可完美运行Google服务(开源版不兼容)。** VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 From a343fb6b0d30c542a1b72a29c7a40fdd8eef84d1 Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 2 Sep 2018 19:32:35 +0800 Subject: [PATCH 093/334] Update CHINESE.md --- CHINESE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 4be7961e4..5c3f4fc82 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -4,9 +4,10 @@ --- **VirtualApp**是一个已经商业化的**App虚拟化引擎**(简称`VA`)。 -**VirtualApp商业版已兼容Android P(9.0)和支持运行纯64位的App。** **VirtualApp商业版现可完美运行Google服务(开源版不兼容)。** +**VirtualApp商业版已兼容Android P(9.0)和支持运行纯64位的App。** + VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 From f39e975acc75b83ac456ef9c55611b421ec22bc8 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 12 Sep 2018 11:29:49 +0800 Subject: [PATCH 094/334] Update CHINESE.md --- CHINESE.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 5c3f4fc82..706fb0c98 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -28,6 +28,22 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+ +9月12日最新商业版更新:
+1、大量适配Gms, 修复Gms运行过程中进程无限重启的问题
+2、重新实现Service的运行机制
+3、完善64bit,提供了部分ROM配置64bit Engine权限的API
+4、修复了4.4设备上的Activity启动问题
+5、支持excludeFromRecent属性
+6、修复Instagram无法Facebook登录的问题
+7、修复Facebook第一次登录闪退的问题
+8、支持以64位模式运行Gms、Google play、Play game
+9、支持在双开/免安装运行的Google play中下载和安装app
+10、修复DownloadManager的BUG
+11、修复Google play返回上层时重启界面的BUG
+12、修复免安装模式下so决策问题
+13、优化构建脚本,便于引入项目
+ 8月26日最新商业版更新:
1、修复移动MM SDK无法启动的问题
2、修复微信摇一摇的BUG
From a42f91b527df9a8adf522f6f892a07f14242df8e Mon Sep 17 00:00:00 2001 From: Lody Date: Sat, 15 Sep 2018 17:20:41 +0800 Subject: [PATCH 095/334] Update CHINESE.md --- CHINESE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 706fb0c98..d09e329ee 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -8,6 +8,9 @@ **VirtualApp商业版已兼容Android P(9.0)和支持运行纯64位的App。** +**VirtualApp商业版提供了同时支持Dalvik和Art的Java Hook(API同Xposed)。** + +tong VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 @@ -28,6 +31,14 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+9月15日最新商业版更新:
+1、修复vivo设备部分Activity无法启动的问题
+2、修复app无法调用外部app选择文件的问题
+3、完善Android P的兼容
+4、兼容Android P的Google服务
+5、解决Messenger部分功能异常
+6、完善IO Redirect
+ 9月12日最新商业版更新:
1、大量适配Gms, 修复Gms运行过程中进程无限重启的问题
From ce27d3375ebcedcf2a08ad6c83722841ee68ef9a Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 28 Sep 2018 12:01:52 +0800 Subject: [PATCH 096/334] Update CHINESE.md --- CHINESE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index d09e329ee..ea2983a40 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -31,6 +31,17 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+ +9月26日最新商业版更新:
+1、解决穿越火线、刺激战场等游戏闪退/封号的问题(额外功能)
+2、修复8.0以下设备Messenger无网络连接的问题
+3、修复双开时外部app卸载时内部app仍然保留的BUG
+4、修复部分腾讯加固无法运行的问题
+5、修复Instagram无法登录Facebook的BUG
+6、修复进程小概率可能重复启动的BUG
+7、修复GET_PERMISSIONS没有获取权限的BUG
+8、修复startActivityIntentSender的BUG
+ 9月15日最新商业版更新:
1、修复vivo设备部分Activity无法启动的问题
2、修复app无法调用外部app选择文件的问题
From 921f5a84e51bba168372fd469abe64f19500fe57 Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 28 Sep 2018 12:06:05 +0800 Subject: [PATCH 097/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index ea2983a40..bea239e82 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -33,7 +33,7 @@ Q Q:10890
9月26日最新商业版更新:
-1、解决穿越火线、刺激战场等游戏闪退/封号的问题(额外功能)
+1、NOP
2、修复8.0以下设备Messenger无网络连接的问题
3、修复双开时外部app卸载时内部app仍然保留的BUG
4、修复部分腾讯加固无法运行的问题
From 2bae9638c9d1f5933b0083480e6d974938918caa Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 28 Sep 2018 12:07:32 +0800 Subject: [PATCH 098/334] Update CHINESE.md --- CHINESE.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index bea239e82..93ed205ba 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -33,14 +33,13 @@ Q Q:10890
9月26日最新商业版更新:
-1、NOP
-2、修复8.0以下设备Messenger无网络连接的问题
-3、修复双开时外部app卸载时内部app仍然保留的BUG
-4、修复部分腾讯加固无法运行的问题
-5、修复Instagram无法登录Facebook的BUG
-6、修复进程小概率可能重复启动的BUG
-7、修复GET_PERMISSIONS没有获取权限的BUG
-8、修复startActivityIntentSender的BUG
+1、修复8.0以下设备Messenger无网络连接的问题
+2、修复双开时外部app卸载时内部app仍然保留的BUG
+3、修复部分腾讯加固无法运行的问题
+4、修复Instagram无法登录Facebook的BUG
+5、修复进程小概率可能重复启动的BUG
+6、修复GET_PERMISSIONS没有获取权限的BUG
+7、修复startActivityIntentSender的BUG
9月15日最新商业版更新:
1、修复vivo设备部分Activity无法启动的问题
From 8768b1deb46d0d2d7229589aa4c8ff78ef7ef5fa Mon Sep 17 00:00:00 2001 From: Lody Date: Thu, 25 Oct 2018 00:07:10 +0800 Subject: [PATCH 099/334] Update CHINESE.md --- CHINESE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 93ed205ba..932662b84 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -32,6 +32,17 @@ Q Q:10890
商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+10月24日最新商业版更新:
+1、解决Android P无法注册超过1000个广播导致的问题
+2、修复可能导致ANR的DeadLock
+3、修复部分app动态加载so失败的问题
+4、修复免安装运行环境下部分机型第一次打开出现黑屏的问题
+5、兼容适配多款主流的Android模拟器
+6、优化启动性能
+7、解决多个内存泄露问题
+8、修复IO Redirect优先级的问题
+ + 9月26日最新商业版更新:
1、修复8.0以下设备Messenger无网络连接的问题
2、修复双开时外部app卸载时内部app仍然保留的BUG
From ed72c178c1a6e187e850f68b5ba2529a2b712c8b Mon Sep 17 00:00:00 2001 From: Lody Date: Thu, 8 Nov 2018 13:50:08 +0800 Subject: [PATCH 100/334] Update CHINESE.md --- CHINESE.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 932662b84..118fe31ef 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -10,7 +10,7 @@ **VirtualApp商业版提供了同时支持Dalvik和Art的Java Hook(API同Xposed)。** -tong + VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 @@ -31,6 +31,14 @@ Q Q:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+11月8号最新商业版更新:
+1、修复新实现的StaticBroadcast导致的兼容性问题
+2、修复Android P上无法使用apache.http.legacy的问题
+3、实现Native trace
+4、优化IO Redirect性能
+5、修复wechat部分时候出现网络无法连接的问题
+6、修复小概率process attach不正确的BUG
+7、开始下一阶段的ROADMAP
10月24日最新商业版更新:
1、解决Android P无法注册超过1000个广播导致的问题
From 50888f6d4fe810171639baf5288d948c18577a96 Mon Sep 17 00:00:00 2001 From: Lody Date: Tue, 20 Nov 2018 15:00:53 +0800 Subject: [PATCH 101/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 118fe31ef..6dc3ea4ae 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -15,7 +15,7 @@ VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间 运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 -VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP云加载、移动办公安全、军队政府保密、手机模拟信息、隐私保护、脚本自动化、自动化测试、游戏手柄免激活等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能--------这都取决于您的想象力。 +VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP云加载、移动办公安全、军队政府保密、手机模拟信息、隐私保护、脚本自动化、自动化测试、手机游戏租号、手机游戏手柄免激活等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能--------这都取决于您的想象力。 申明 --- From c862b755ebdc6ccbe65420581efea8e77f71f0a4 Mon Sep 17 00:00:00 2001 From: Lody Date: Mon, 26 Nov 2018 15:47:54 +0800 Subject: [PATCH 102/334] Update CHINESE.md --- CHINESE.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 6dc3ea4ae..e09520ef9 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,10 +27,18 @@ VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP
负责人:张总
手机:130-321-77777
-Q Q:10890
+微信:z10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
+11月26号最新商业版更新:
+1、修复WebView在少数机型加载失败的情况
+2、修复Lib决策的问题
+3、修复部分华为机型无法读取内存卡的问题
+4、修复Service可能存在的问题
+5、允许根据intent判断Activity是否在外部启动
+6、修复部分机型上Gms和Google Play启动到了不正确的环境
+ 11月8号最新商业版更新:
1、修复新实现的StaticBroadcast导致的兼容性问题
2、修复Android P上无法使用apache.http.legacy的问题
From 65a9855ddf759c89b131510713519d41d3001576 Mon Sep 17 00:00:00 2001 From: Lody Date: Mon, 26 Nov 2018 18:14:11 +0800 Subject: [PATCH 103/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index e09520ef9..9120f8e6e 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -27,7 +27,7 @@ VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP
负责人:张总
手机:130-321-77777
-微信:z10890
+微信:10890

商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
From 34b5325bf88cfbcac4a326fd9a72ceb82e2503e9 Mon Sep 17 00:00:00 2001 From: Lody Date: Sat, 15 Dec 2018 11:22:22 +0800 Subject: [PATCH 104/334] Update CHINESE.md --- CHINESE.md | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 9120f8e6e..045e0944c 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -1,34 +1,40 @@ [![VA banner](https://raw.githubusercontent.com/asLody/VirtualApp/master/Logo.png)](https://github.com/asLody/VirtualApp) -简介 +项目简介 --- **VirtualApp**是一个已经商业化的**App虚拟化引擎**(简称`VA`)。 -**VirtualApp商业版现可完美运行Google服务(开源版不兼容)。** +**VirtualApp商业版现可完美运行Google服务(开源版本不兼容)。** -**VirtualApp商业版已兼容Android P(9.0)和支持运行纯64位的App。** +**VirtualApp商业版已兼容最新Android P(9.0)和支持运行纯64位的App。** **VirtualApp商业版提供了同时支持Dalvik和Art的Java Hook(API同Xposed)。** -VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 +VirtualApp是由`罗盒科技`开发并运营的商业项目,VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 -VA目前被广泛应用于插件化开发、无感知热更新、APP多开、APP云加载、移动办公安全、军队政府保密、手机模拟信息、隐私保护、脚本自动化、自动化测试、手机游戏租号、手机游戏手柄免激活等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能--------这都取决于您的想象力。 +VA目前被广泛应用于`插件化开发、无感知热更新、云控自动化、多开、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府保密、手机模拟信息、脚本自动化、自动化测试`等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能-----这都取决于您的想象力。 + +**Github上代码**已在2017年12月份**停止更新***,商业版代码在持续更新中,并有以下提升:`1、全新的代码特征,2、框架优化,性能大幅提升,3、手机系统及APP兼容性大幅提升,4、完美运行Google服务,5、兼容最新Android P(9.0),6、支持运行纯64位App,7、支持Dalvik和Art的Java Hook(API同Xposed),8、增加定位模拟代码,9、增加改机代码,10、其他180多项问题的修复和改进`,详情请见下表。 + + + +**授权说明** + +罗盒科技在深圳及山东设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。` + -申明 ---- -  VirtualApp是罗盒科技开发运营,罗盒科技在深圳及山东设有公司,于2015年至2018年陆续申请多项VirtualApp知识产权。当您需要将VirtualApp用于商业用途时,请购买商业授权。
-
-  您如果未经授权将VirtualApp的代码作为您自己的代码用于内部使用、商业牟利或上传应用市场,我们将直接报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。
-
-  目前VirtualApp拥有各行业众多授权客户,集成VirtualApp代码的APP日启动量超过2亿次。购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利。获取VirtualApp商业授权后您将得到:商业版代码、说明接入文档、微信和QQ群技术支持。

负责人:张总
手机:130-321-77777
微信:10890

+ +**严重声明** +您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
+ 商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
11月26号最新商业版更新:
From dd4032e4b27b4c2eccebfad187ad4ac039fa6c15 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 19 Dec 2018 20:17:36 +0800 Subject: [PATCH 105/334] Update CHINESE.md --- CHINESE.md | 267 +++++++++++++++++++---------------------------------- 1 file changed, 95 insertions(+), 172 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 045e0944c..d9a9274b9 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -2,28 +2,29 @@ 项目简介 --- -**VirtualApp**是一个已经商业化的**App虚拟化引擎**(简称`VA`)。 - -**VirtualApp商业版现可完美运行Google服务(开源版本不兼容)。** - -**VirtualApp商业版已兼容最新Android P(9.0)和支持运行纯64位的App。** - -**VirtualApp商业版提供了同时支持Dalvik和Art的Java Hook(API同Xposed)。** - - VirtualApp是由`罗盒科技`开发并运营的商业项目,VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 VA目前被广泛应用于`插件化开发、无感知热更新、云控自动化、多开、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府保密、手机模拟信息、脚本自动化、自动化测试`等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能-----这都取决于您的想象力。 -**Github上代码**已在2017年12月份**停止更新***,商业版代码在持续更新中,并有以下提升:`1、全新的代码特征,2、框架优化,性能大幅提升,3、手机系统及APP兼容性大幅提升,4、完美运行Google服务,5、兼容最新Android P(9.0),6、支持运行纯64位App,7、支持Dalvik和Art的Java Hook(API同Xposed),8、增加定位模拟代码,9、增加改机代码,10、其他180多项问题的修复和改进`,详情请见下表。 +**Github上代码**已在2017年12月份**停止更新**,商业版代码在持续更新中,并有以下提升: +1. 全新的代码特征 +2. 框架优化,性能大幅提升 +3. 手机系统及APP兼容性大幅提升 +4. 完美运行Google服务 +5. 兼容最新Android P(9.0) +6. 支持运行纯64位App +7. 支持Dalvik和Art的Java Hook(API同Xposed) +8. 增加定位模拟代码 +9. 增加改机代码 +10. 其他180多项问题的修复和改进,详情请见下表 **授权说明** -罗盒科技在深圳及山东设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。` +罗盒科技在深圳及山东设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
@@ -35,110 +36,88 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 **严重声明** 您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
-商业版代码保持每月1-2次以上频率持续更新,并对Android 9.0进行大量适配,保证了兼容性。
- -11月26号最新商业版更新:
-1、修复WebView在少数机型加载失败的情况
-2、修复Lib决策的问题
-3、修复部分华为机型无法读取内存卡的问题
-4、修复Service可能存在的问题
-5、允许根据intent判断Activity是否在外部启动
-6、修复部分机型上Gms和Google Play启动到了不正确的环境
- -11月8号最新商业版更新:
-1、修复新实现的StaticBroadcast导致的兼容性问题
-2、修复Android P上无法使用apache.http.legacy的问题
-3、实现Native trace
-4、优化IO Redirect性能
-5、修复wechat部分时候出现网络无法连接的问题
-6、修复小概率process attach不正确的BUG
-7、开始下一阶段的ROADMAP
- -10月24日最新商业版更新:
-1、解决Android P无法注册超过1000个广播导致的问题
-2、修复可能导致ANR的DeadLock
-3、修复部分app动态加载so失败的问题
-4、修复免安装运行环境下部分机型第一次打开出现黑屏的问题
-5、兼容适配多款主流的Android模拟器
-6、优化启动性能
-7、解决多个内存泄露问题
-8、修复IO Redirect优先级的问题
- - -9月26日最新商业版更新:
-1、修复8.0以下设备Messenger无网络连接的问题
-2、修复双开时外部app卸载时内部app仍然保留的BUG
-3、修复部分腾讯加固无法运行的问题
-4、修复Instagram无法登录Facebook的BUG
-5、修复进程小概率可能重复启动的BUG
-6、修复GET_PERMISSIONS没有获取权限的BUG
-7、修复startActivityIntentSender的BUG
- -9月15日最新商业版更新:
-1、修复vivo设备部分Activity无法启动的问题
-2、修复app无法调用外部app选择文件的问题
-3、完善Android P的兼容
-4、兼容Android P的Google服务
-5、解决Messenger部分功能异常
-6、完善IO Redirect
- - -9月12日最新商业版更新:
-1、大量适配Gms, 修复Gms运行过程中进程无限重启的问题
-2、重新实现Service的运行机制
-3、完善64bit,提供了部分ROM配置64bit Engine权限的API
-4、修复了4.4设备上的Activity启动问题
-5、支持excludeFromRecent属性
-6、修复Instagram无法Facebook登录的问题
-7、修复Facebook第一次登录闪退的问题
-8、支持以64位模式运行Gms、Google play、Play game
-9、支持在双开/免安装运行的Google play中下载和安装app
-10、修复DownloadManager的BUG
-11、修复Google play返回上层时重启界面的BUG
-12、修复免安装模式下so决策问题
-13、优化构建脚本,便于引入项目
- -8月26日最新商业版更新:
-1、修复移动MM SDK无法启动的问题
-2、修复微信摇一摇的BUG
-3、修复中兴设备不稳定的BUG
-4、支持ARM64下的IO Redirect
-5、修复USE_OUTSIDE模式下外部app更新时,内部app没有更新的BUG
- -8月17日最新商业版更新:
-1、兼容最新Android 9.0(代号: pie) 及正式版之前发布的四个Preview版本
-2、兼容内置houdini的x86设备
-3、WindowPreview技术,使app启动与真实app达到一样的速度
-4、新的ActivityStack以提高app运行质量
-5、解决接入Atlas Framework的app运行异常的问题
-6、现在可以定义虚拟app返回桌面的具体行为
-7、现在双开模式下app随系统动态更新,不需要手动检查
-8、支持targetSdkVersion >= 26时仍可正常运行低版本的app
-9、兼容腾讯游戏管家的QDroid虚拟引擎 (beta)
-10、大量重构底层代码,大幅提升运行速度
-11、修复网易新闻分享到微博后无法取消的问题
-12、修复App自定义权限无法识别的问题
-13、修复墨迹天气app无法启动的问题
-13、修复部分政府app无法启动的问题
-14、API的变动详见代码
- -8月6日最新商业版更新:
-1、修复三星系列应用的相互调用问题
-2、修复小米应用在非小米系统的账号问题
-3、修复分享/发送等第三方调用,返回页面不正常
-4、修复应用宝提示不能安装
-5、调用第三方app,对uri进行加密
-6、适配前刘海
-7、适配小米rom的hook
-8、适配努比亚录音问题
-9、内部悬浮窗权限控制
-9、优化自定义通知栏的处理
-10、修复Context的INCLUDE_CODE权限问题
-11、适配华为,oppo的角标
-12、修复百度视频的进程重启问题
-13、修复某些snapchat的无法启动问题
-
-2018年1月1日至7月31日历史更新:
+2018年1月1日至2018年12月13号商业版代码更新内容:
+182、修复WebView在少数机型加载失败的情况
+181、修复Lib决策的问题
+180、修复部分华为机型无法读取内存卡的问题
+179、修复Service可能存在的问题
+178、允许根据intent判断Activity是否在外部启动
+177、修复部分机型上Gms和Google Play启动到了不正确的环境
+176、修复新实现的StaticBroadcast导致的兼容性问题
+175、修复Android P上无法使用apache.http.legacy的问题
+174、实现Native trace
+173、优化IO Redirect性能
+172、修复wechat部分时候出现网络无法连接的问题
+171、修复小概率process attach不正确的BUG
+170、开始下一阶段的ROADMAP
+169、解决Android P无法注册超过1000个广播导致的问题
+168、修复可能导致ANR的DeadLock
+167、修复部分app动态加载so失败的问题
+166、修复免安装运行环境下部分机型第一次打开出现黑屏的问题
+165、兼容适配多款主流的Android模拟器
+164、优化启动性能
+163、解决多个内存泄露问题
+162、修复IO Redirect优先级的问题
+161、修复8.0以下设备Messenger无网络连接的问题
+160、修复双开时外部app卸载时内部app仍然保留的BUG
+159、修复部分腾讯加固无法运行的问题
+158、修复Instagram无法登录Facebook的BUG
+157、修复进程小概率可能重复启动的BUG
+156、修复GET_PERMISSIONS没有获取权限的BUG
+155、修复startActivityIntentSender的BUG
+154、修复vivo设备部分Activity无法启动的问题
+153、修复app无法调用外部app选择文件的问题
+152、完善Android P的兼容
+151、兼容Android P的Google服务
+150、解决Messenger部分功能异常
+149、完善IO Redirect
+148、大量适配Gms, 修复Gms运行过程中进程无限重启的问题
+147、重新实现Service的运行机制
+146、完善64bit,提供了部分ROM配置64bit Engine权限的API
+145、修复了4.4设备上的Activity启动问题
+144、支持excludeFromRecent属性
+143、修复Instagram无法Facebook登录的问题
+142、修复Facebook第一次登录闪退的问题
+141、支持以64位模式运行Gms、Google play、Play game
+140、支持在双开/免安装运行的Google play中下载和安装app
+139、修复DownloadManager的BUG
+138、修复Google play返回上层时重启界面的BUG
+137、修复免安装模式下so决策问题
+136、优化构建脚本,便于引入项目
+135、修复移动MM SDK无法启动的问题
+134、修复微信摇一摇的BUG
+133、修复中兴设备不稳定的BUG
+132、支持ARM64下的IO Redirect
+131、修复USE_OUTSIDE模式下外部app更新时,内部app没有更新的BUG
+130、兼容最新Android 9.0(代号: pie) 及正式版之前发布的四个Preview版本
+129、兼容内置houdini的x86设备
+128、WindowPreview技术,使app启动与真实app达到一样的速度
+127、新的ActivityStack以提高app运行质量
+126、解决接入Atlas Framework的app运行异常的问题
+125、现在可以定义虚拟app返回桌面的具体行为
+124、现在双开模式下app随系统动态更新,不需要手动检查
+123、支持targetSdkVersion >= 26时仍可正常运行低版本的app
+122、兼容腾讯游戏管家的QDroid虚拟引擎 (beta)
+121、大量重构底层代码,大幅提升运行速度
+120、修复网易新闻分享到微博后无法取消的问题
+119、修复App自定义权限无法识别的问题
+118、修复墨迹天气app无法启动的问题
+117、修复部分政府app无法启动的问题
+116、API的变动详见代码
+115、修复三星系列应用的相互调用问题
+114、修复小米应用在非小米系统的账号问题
+113、修复分享/发送等第三方调用,返回页面不正常
+112、修复应用宝提示不能安装
+111、调用第三方app,对uri进行加密
+110、适配前刘海
+109、适配小米rom的hook
+108、适配努比亚录音问题
+107、内部悬浮窗权限控制
+106、优化自定义通知栏的处理
+105、修复Context的INCLUDE_CODE权限问题
+104、适配华为,oppo的角标
+103、修复百度视频的进程重启问题
+102、修复某些snapchat的无法启动问题
101、适配autofill服务,例如piexl系列
100、完善64位的io hook
99、优化hook库的兼容性,加回dlopen
@@ -239,61 +218,5 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 4、与开源版不同的特征
3、解决了微信被封的一些问题
2、修复了部分机型兼容性
-1、修复了12个小BUG - - -已支持的加固(不断更新) ----------- -* 360加固 -* 腾讯加固 -* 梆梆加固 -* 梆梆企业版(12306客户端 Pass) -* 爱加密 -* 百度加固 -* 娜迦加固 -* 乐变加固 -* 网易易盾 -* 通付盾 -* (已支持的加固均可通过VA来脱壳,本技术不公开) - - -Google Play Framework ------------ -在google service新版本,存在兼容适配问题,暂时屏蔽 - - -使用说明 ----------- - -**前往你的Application并添加如下代码:** -```java - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - try { - VirtualCore.getCore().startup(base); - } catch (Throwable e) { - e.printStackTrace(); - } - } -``` -**安装App:** -```java - VirtualCore.getCore().installApp({APK PATH}, flags); -``` -**启动App:** -```java - VirtualCore.getCore().launchApp({PackageName}); -``` -**移除App:** -```java - VirtualCore.getCore().uninstallApp({PackageName}); -``` -**该App的基本信息:** -```java - VirtualCore.getCore().findApp({PackageName}); -``` +1、修复了12个小BUG
-BUG反馈 ------------- -zl@aluohe.com From f29be1c7c19daef594af9fc6e28e0bbe590ae84a Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 19 Dec 2018 20:18:17 +0800 Subject: [PATCH 106/334] Update CHINESE.md --- CHINESE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index d9a9274b9..5a4210b55 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -36,7 +36,9 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 **严重声明** 您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
-2018年1月1日至2018年12月13号商业版代码更新内容:
+**2018年1月1日至2018年12月13号商业版代码更新内容** + + 182、修复WebView在少数机型加载失败的情况
181、修复Lib决策的问题
180、修复部分华为机型无法读取内存卡的问题
From b7c3789a7d0e61637105e9ebb3c4b1097b584ce9 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 19 Dec 2018 20:18:41 +0800 Subject: [PATCH 107/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 5a4210b55..9c8ef6fc0 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -36,9 +36,9 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 **严重声明** 您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
-**2018年1月1日至2018年12月13号商业版代码更新内容** +**2018年1月1日至2018年12月13号商业版代码更新内容** 182、修复WebView在少数机型加载失败的情况
181、修复Lib决策的问题
180、修复部分华为机型无法读取内存卡的问题
From b514dc7b2211f2712ebafca180c9f06a5fafce48 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 19 Dec 2018 20:18:56 +0800 Subject: [PATCH 108/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 9c8ef6fc0..0a31260c8 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -39,6 +39,7 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 **2018年1月1日至2018年12月13号商业版代码更新内容** + 182、修复WebView在少数机型加载失败的情况
181、修复Lib决策的问题
180、修复部分华为机型无法读取内存卡的问题
From 1e0d17cb34e114ea0e6c292e7956bb4fa0f01c2b Mon Sep 17 00:00:00 2001 From: Lody Date: Thu, 20 Dec 2018 08:54:05 +0800 Subject: [PATCH 109/334] Update CHINESE.md --- CHINESE.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 0a31260c8..77b0a44f2 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -22,7 +22,8 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 10. 其他180多项问题的修复和改进,详情请见下表 -**授权说明** +授权说明 +------ 罗盒科技在深圳及山东设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` @@ -33,7 +34,9 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 微信:10890

-**严重声明** +严重声明 +------ + 您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
From 5986bd36721fe7cc376dd2dde7c3ab9f2c1e07bf Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 21 Dec 2018 14:17:42 +0800 Subject: [PATCH 110/334] Update README.md --- README.md | 296 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 222 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 24a891a42..466b91b13 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,224 @@ [![VA banner](https://raw.githubusercontent.com/asLody/VirtualApp/master/Logo.png)](https://github.com/asLody/VirtualApp) -[中国人猛戳这里](CHINESE.md "中文") - -About ------ -**VirtualApp** is an open platform for Android that allows you to create a `Virtual Space`, -you can install and run apk inside. Beyond that, VirtualApp is also a `Plugin Framework`, -the plugins running on VirtualApp does not require any constraints. -VirtualApp does **not** require root, it is running on the `local process`. - -NOTICE -------- -**This project has been authorized by the business.** - -**You are not allowed to modify the app module and put to the software market, if you do that, The consequences you know :)** - -**VirtualApp is not free, If you need to use the lib code, please send email to me :)** - -Background ----------- - -VirtualApp was born in early 2015, Originally, it is just a simple plugin framework, -But as time goes on, -the compatibility of it is getting better and better. -in the end, it evolved into a `Virtual Container`. - - -Get started ------------ -If you use latest android studio (version 2.0 or above), please disable `Instant Run`. -Open `Setting | Build,Exception,Deployment`, and disable `Enable Instant Run to hot swap...` - -**Goto your Application and insert the following code:** -```java - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - try { - VirtualCore.get().startup(base); - } catch (Throwable e) { - e.printStackTrace(); - } - } -``` - -**Install a virtual App:** -```java - VirtualCore.get().installPackage({APK PATH}, flags); - -``` - -**Launch a virtual App:** -```java - //VirtualApp support multi-user-mode which can run multiple instances of a same app. - //if you don't need this feature, just set `{userId}` to 0. - Intent intent = VirtualCore.get().getLaunchIntent({PackageName}, {userId}); - VActivityManager.get().startActivity(intent, {userId}); -``` - -**Uninstall a virtual App:** -```java - VirtualCore.get().uninstallPackage({PackageName}); -``` - -More details, please read the source code of demo app, :-) - -Documentation -------------- - -VirtualApp currently has **no documentation**, If you are interested in VirtualApp, please send email to me. - -Contact us ------------- - - zl@aluohe.com +[中文版](CHINESE.md "中文") + +Project Profile +--------------- + +VirtualApp is a commercial project developed and operated by Luohe technology, which creates a virtual space within your App. You can `install, start and uninstall APK arbitrarily in the virtual space`, which is isolated from the outside, like a *sandbox*. +APK running in VA does not need to be `installed externally`, that is, the VA supports running APK without installation. +VA is currently widely used in plug-in development, non-thermal update, cloud control automation, multi-open, mobile game rent number, mobile game handle activation free, block chain, mobile office security, military and government secrecy, mobile phone simulation information, script automation, automated testing and other technical fields, but it is not limited to this. Android itself is an extremely open platform, `and the ability to run APK without installing it opens up unlimited possibilities -- which depend on your imagination.` +The code on Github has been updated since December 2017. The commercial version of the code is still being updated, with the following improvements: + +1. New Code Characteristics +2. Framework optimization and performance improvement +3. Compatibility of mobile phone system and APP has been greatly improved +4. Run Google services perfectly +5. Compatibility with the latest Android P (9.0) +Support running 64-bit App +7. Java Hook that supports Dalvik and Art (API and Xposed) +8. Add positioning simulation code +9. Add the machine changing code +10. Please refer to the table below for details of the repair and improvement of more than 180 other problems + + +Authorization Note +------------------ + +Luohe Technology has set up companies in Shenzhen and Shandong. From 2015 to 2018, it applied for many VirtualApp intellectual property rights, which are protected by the Intellectual Property Law of the People's Republic of China. When you need to use the VirtualApp code on Github, please purchase the commercial license. After obtaining the commercial license, you will receive the full source code of the commercial version of VirtualApp provided by us. Dozens of authorized customers pay for the use of VirtualApp commercial code, and the number of APPs that integrate VirtualApp code starts more than 200 million times a day. Thousands of Android engineers provide us with user feedback in different scenarios, and VirtualApp commercial version code has become increasingly sophisticated through the continuous efforts of our technical team to optimize. After you get the authorization, you will become one of them and enjoy the fruits of continuous iteration and improvement. And we can cooperate with our authorized customers in operation, technology and business. + + +Person in charge: General Zhang
+Mobile:+86 1303217777 7
+Wechat: 10890
+ + +Strictness Disclaimer +--------------------- + +If you use VirtualApp for internal use, commercial profit or upload to the application market without authorization, we will directly collect evidence and report to the police (copyright infringement) or prosecute, which will cause criminal liability and legal proceedings to your company and affect your company's goodwill and investment. Buying a commercial license saves you a lot of development, testing, and refining time, allowing you more time to innovate and monetize. + +The updating contents of commercial version code from January 1, 2018 to December 13, 2018. + +182. Fix WebView loading failure in a few models
+181. Fix Lib decision problems
+180. Fix the problem that some Huawei models could not read memory CARDS
+179. Fix possible problems with the Service
+178. Allow judging whether an Activity is started externally based on intent
+177. Fix incorrect environment boot of Gms and Google Play on some models
+176. Fix compatibility problems caused by the StaticBroadcast new implementation
+175. Fix the problem that apache. HTTP. Legacy cannot be used on Android P
+174. Implement Native trace
+173. Optimize IO Redirect performance
+172. Fix the occasional network failure of wechat
+171. Fix bugs with incorrect small probability process attach
+170. ROADMAP for the next stage
+169. Solve the problem caused by Android P's inability to register more than 1000 broadcasts
+168. Fix DeadLock that may cause ANR
+167. Fix the problem of partial app dynamic loading failure
+166. Fix the problem that black screen appears when some models are opened for the first time under the operating environment without installation
+165. Compatible with many mainstream Android emulators
+164. Optimize start-up performance
+163. Resolve multiple memory leaks
+162. Fix IO Redirect priority issues
+161. Fix the problem of no network connection for Messenger device below 8.0
+160. Fix Bug that remained in the internal app when the external app was uninstalled in dual-open mode
+159. Fix the problem of some tencent reinforcement can not run
+158. Fix the BUG that Instagram could not log into Facebook
+157. Fix Bug that may be started repeatedly with low probability
+156. Fix Bug of the GET_PERMISSIONS without authorization
+155. Fix Bug of starting Activity Intent Sender
+154. Fix the problem that activity on some vivo devices could not be started
+153. Fix the problem that the app could not call the external app to select the file
+152. Improve the compatibility of Android P
+151. Google service compatible with Android P
+150. Solve some abnormal functions of Messenger
+149. Improve IO Redirect
+148. A large number of Gms are adapted to fix the problem of unlimited process restart during Gms operation
+147. Re-implement the operation mechanism of Service
+146. Improve 64 bit and provide API for some ROM configuration 64bit Engine permissions
+145. Fix Activity startup problem on 4.4 device
+144. Support the exclude From Recent attribute
+143. Fix the problem that Instagram could not log into Facebook
+142. Fix the problem of Facebook's first login flashback
+141. Support to run Gms, Google play and play game in 64-bit mode
+140. Support downloading and installing apps in Google Play with dual-open/install-free running
+139. Fix Bug of Download Manager
+138. Fix the BUG of restarting the interface when Google play returned to the upper layer
+137. Fix the so decision-making problem in the installation-free mode
+136. Optimize the build script to facilitate the introduction of projects
+135. Fix the problem that the mobile MM SDK could not be started
+134. Fix the BUG of WeChat shake
+133. Fix the unstable BUG of ZTE equipment
+132. Support ARM64 IO Redirect
+131. Fix the BUG that no updates are made to the internal app when the external app is updated in USE_OUTSIDE mode
+130. Compatible with the latest version of Android 9.0(code-named pie) and the four Preview versions released before the official version
+129. Compatible with x86 devices with built-in Houdini
+128. Windows preview technology enables App to start at the same speed as real App
+127. New Activity Stack to improve running quality of APP
+126. Solve the abnormal operation of App connected to Atlas Framework
+125. Be able to define the specific behavior of the virtual app returning to the desktop
+124. Now the app is dynamically updated with the system in double-open mode, without manual check
+123. When target Sdk Version >= 26, the lower version of the app can still run normally
+122. QDroid virtual engine (beta) compatible with tencent game manager
+121. Refactor a lot of underlying code to greatly improve the running speed
+120. Fix the problem that netease news cannot be cancelled after sharing on weibo
+119. Fix the problem that App custom permissions cannot be recognized
+118. Fix the problem that the app could not be started due to ink stains
+117. Fix the problem that some government apps could not be started
+116. See the code for changes to the API
+115. Fixed the mutual call problem of Samsung series of applications
+114. Fix the account problems of Xiaomi applications in non-xiaomi systems
+113. Repair third-party calls such as share/send, and the returned page is abnormal
+112. Fix the problem that App prompt cannot be installed
+111. Use the third-party App and encrypt the uri
+110. Adapt to the bangs
+109. Adapt to the hook of Xiaomi ROM
+108. Adapt to the problem of Nubian recording
+107. Permission control of internal suspension window
+106. Optimize the processing of customized notification bar
+105. Fix the INCLUDE_CODE permission problem of Context
+104. Adapt to corner marks of Huawei and Oppo
+103. Fix the problem of Baidu video process restart
+102. Fix some snap chat start-up problems
+101. Adapt to autofill service, such as piexl series
+100. Improve 64-bit IO hook
+99. Optimize hook library compatibility, add back dlopen
+98. The so of the 64-bit extension package is moved to the 32-bit master package. (after jni code changes, please build it once before running)
+Notification Bar Change: Adapt 8.1 Notification Channel; Remove all notifications of the application when the application is removed
+96. Compatible with some Apps, need to set android:largeHeap=true
+95. Fix the problem of ffmpeg library video can not play
+94. Optimize horizontal and vertical screen switching
+93. Reduce the limit of calling external activities with intent.action_view.
+92. Compatible with MG SDK
+91. 64-bit support is still in development
+90. Update the confusion configuration app/proguard-rules.pro, must add the rule -dontshrink
+89. Optimize the simulation model, for example: after simulation, device verification does not appear in some Apps
+88. Improve dex2oat compatibility
+87. Optimize simulation positioning
+86. Remove dlopen
+85. TargetVersion can be changed to 26: support dynamic permission application for app with targetVersion < 23 and file Uri with targetVersion < 24
+84. Install Package changed to the default asynchronous form
+83. Support 64-bit mode and switch back to aidl
+82. Remove Setting Handler can now dynamically set special rules, which are stored and do not need to be set repeatedly
+81. Add 2 native_setup
+80. Improve jobService compatibility
+79. Shortcut Service: Associate VASettings.ENABLE_INNER_SHORTCUT
+78. For the sake of stability and operational efficiency, remove the previous version of bluetooth and wifi, and do not declare the adaption of permissions.
+77. Increase the broadcast Constants of app startup exceptions with ACTION_PROCESS_ERROR
+76. Fix a few game screen judgment problems
+75. Demo adds model simulation
+74. Vivo ADAPTS a custom permission (background popover). VA is to return a historical activity to the foreground, which vivo needs.
+73. If there is no bluetooth permission, return the default value (for overseas use)
+72. Fix the uid permission check problem
+71. Security update and file permission control for internal applications
+70. Improve the compatibility of internal app calls, third-party login and sharing
+69. Automatically filter unauthorized external contentproviders
+68. Added function: check the permission of internal app (closed by default)
+67. Model simulation: Build class and build.prop
+66. Improve app compatibility for legu reinforcement
+65. Adapt to Samsung wifimanager
+64. Fix a parameter passing problem in ipc framework (IPCMethod class must be updated)
+63. Complete the hook of 7.0 notice bar
+62. Fix hook of 8.0 dynamic shortcut menu
+61. Setting Handler adds an adaptor interface, mainly suitable for various games
+60. Function changes: Google automatic installation to manual installation, to avoid the first time to start too long
+59. Access to an external Content Provider can be prohibited
+58. Adapt to the number of Huawei desktop icons
+57. Permission classification annotation, indicating that permission can be deleted
+56. Add dual-open mode App to follow the external upgrade switch
+55. Improve jni compatibility of app
+54. Improve compatibility with other plug-in frameworks for app integration
+53. Add setting interface and set according to the package name
+52. Increase the Uri adaptation range to support sharing and viewing files through uris
+51. Fix a problem with Samsung 8.0
+50. Improve the compatibility of app components with the system, better compatible with chrome webview and Google service.
+49. Improve the stability of ART
+48. Increase the scope of camera adaptation
+47. Support shortcut management of internal App under 8.0
+46. Fix exec exceptions
+45. Improve stability (Fix WeChat login backout)
+44. Solve the problem of WeChat database crash
+43. Fixed part 4.4 equipment crash
+42. Fix the problems that the background application is easy to be killed, tudou video black screen, sina weibo cannot be opened, and youku cannot exit after two returns.
+41. Add the survival mechanism of the application, and double-open APP is more difficult to be killed.
+40. Optimize start-up performance of virtual engine.
+39. Compatible with most of the reinforcement and the compatibility of third-party APP increased by 40% compared with the previous version.
+38. Fixed some ROMs with incorrect shortcut icons
+37. Compatibility with previous component Stub File Provider
+36. Virtual IMEI for adapting part of the new ROM
+35. Improve process initialization code and increase stability
+34. Add internal transmission Intent.ACTION_BOOT_COMPLETED broadcast and the switch can be set
+33. Adapt to the Google play game, and support the game to log in with Google
+32. Compatible with Google service framework of android O
+31. Compatible with android O shortcuts
+30. Adapt to headset mode
+29. Some ROMs limit the size of intent. Demo adds zoom shortcut icon code
+28. Fix the Bug in the case of multiple openings
+27. Fix the Bug in Media Controller in some cases
+26. Fix Stub File Provider error of 4.1.2
+25. Share uri processing
+24. Fix the callback of cross-app call Activity
+23. Notification bar blocking switch of foreground service
+22. Attached doc
+21. Improve the CHOOSE callback of intent within VA
+20. The notification bar of Android O is compatible with 2
+19. Optimize ipc framework to improve the survival accuracy of binder
+18. JNI log switch Android.mk: LOCAL_CFLAGS+=-DLOG_ENABLE
+17. Confusion Configuration
+16. Android O Notice Bar Adaptation
+15. Fix problems with some app network CARDS
+14. Dl_open (jni load) compatible with android 8.0
+13. Fix the Bug of Huawei emui8.0
+12. Improve positioning
+11. Set up mobile phone information and imei camouflage algorithm
+10. Adapt to a certain function of 8.0(main app: whats App)
+9. Fix the problem that internal WeChat and other applications could not update pictures and video
+8. Demo adds installation monitoring and automatically updates the application of clone mode
+7. 7.0 File Provider Adaptation
+6. Add location code
+5. Architectural optimization of code
+4. Different features from the open source version
+3. Solve some problems of WeChat sealing
+2. Fix compatibility of some models
+1. Fix 12 minor bugs From 625ac830570e54a72e873a13e883ba40d2b0a81f Mon Sep 17 00:00:00 2001 From: Lody Date: Sat, 5 Jan 2019 11:58:24 +0800 Subject: [PATCH 111/334] Update CHINESE.md --- CHINESE.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 77b0a44f2..a6681a2f2 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -39,6 +39,14 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
+**最新一期更新内容** + +1、修复华为设备部分app无法识别存储的问题
+2、修复启动进程可能失败导致app无法运行的问题
+3、修复4.4设备部分native符号无法找到的问题
+4、修复部分设备WebView包名获取失败的问题
+5、修复Service细节处理的问题
+6、优化启动速度
**2018年1月1日至2018年12月13号商业版代码更新内容** From 33ba1b26ecbb989c2cf5aa87bfda118b332aa1aa Mon Sep 17 00:00:00 2001 From: Lody Date: Thu, 17 Jan 2019 13:20:05 +0800 Subject: [PATCH 112/334] Update CHINESE.md --- CHINESE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index a6681a2f2..cd88db393 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -31,7 +31,7 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动
负责人:张总
手机:130-321-77777
-微信:10890
+QQ/微信:10890

严重声明 @@ -39,7 +39,7 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
-**最新一期更新内容** +**2019年1月份更新内容** 1、修复华为设备部分app无法识别存储的问题
2、修复启动进程可能失败导致app无法运行的问题
From ce29db73ec18d73ef3ed6bc7a76a81b0b807f9ee Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 3 Mar 2019 12:51:25 +0800 Subject: [PATCH 113/334] Update CHINESE.md --- CHINESE.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index cd88db393..52213bee6 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -39,14 +39,18 @@ QQ/微信:10890
您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
-**2019年1月份更新内容** - -1、修复华为设备部分app无法识别存储的问题
-2、修复启动进程可能失败导致app无法运行的问题
-3、修复4.4设备部分native符号无法找到的问题
-4、修复部分设备WebView包名获取失败的问题
-5、修复Service细节处理的问题
-6、优化启动速度
+2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 + + +**2018年1月1日至2018年2月28号商业版代码更新内容** + +188、修复华为设备部分app无法识别存储的问题 +187、修复启动进程可能失败导致app无法运行的问题 +186、修复4.4设备部分native符号无法找到的问题 +185、修复部分设备WebView包名获取失败的问题 +184、修复Service细节处理的问题 +183、优化启动速度 +182、修复WebView在少数机型加载失败的情况 **2018年1月1日至2018年12月13号商业版代码更新内容** From 66ab677d8c01f133f2de63696aa4906e3ef70dd1 Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 3 Mar 2019 12:51:56 +0800 Subject: [PATCH 114/334] Update CHINESE.md --- CHINESE.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 52213bee6..23f5d3a50 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -44,13 +44,13 @@ QQ/微信:10890
**2018年1月1日至2018年2月28号商业版代码更新内容** -188、修复华为设备部分app无法识别存储的问题 -187、修复启动进程可能失败导致app无法运行的问题 -186、修复4.4设备部分native符号无法找到的问题 -185、修复部分设备WebView包名获取失败的问题 -184、修复Service细节处理的问题 -183、优化启动速度 -182、修复WebView在少数机型加载失败的情况 +188、修复华为设备部分app无法识别存储的问题
+187、修复启动进程可能失败导致app无法运行的问题
+186、修复4.4设备部分native符号无法找到的问题
+185、修复部分设备WebView包名获取失败的问题
+184、修复Service细节处理的问题
+183、优化启动速度
+182、修复WebView在少数机型加载失败的情况
**2018年1月1日至2018年12月13号商业版代码更新内容** From fa93ffe11e7141416056cb230700c59288b8c705 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 6 Mar 2019 11:25:06 +0800 Subject: [PATCH 115/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 23f5d3a50..ae93e766d 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -32,6 +32,7 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 负责人:张总
手机:130-321-77777
QQ/微信:10890
+Company Email: Lody@aluohe.com

严重声明 From 6f22cd86639a872ea54a0505dc279fc80256a9d1 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 6 Mar 2019 18:12:22 +0800 Subject: [PATCH 116/334] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 466b91b13..46cf1d4e4 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,9 @@ Luohe Technology has set up companies in Shenzhen and Shandong. From 2015 to 201 Person in charge: General Zhang
-Mobile:+86 1303217777 7
+Mobile: +86 1303217777 7
Wechat: 10890
+Company email: Lody@aluohe.com Strictness Disclaimer From e0e18449e14e8fd0970c2da47054b9d1b39804bb Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Mar 2019 12:59:24 +0800 Subject: [PATCH 117/334] Update CHINESE.md --- CHINESE.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index ae93e766d..bb194c4c2 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -10,11 +10,11 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 **Github上代码**已在2017年12月份**停止更新**,商业版代码在持续更新中,并有以下提升: -1. 全新的代码特征 -2. 框架优化,性能大幅提升 -3. 手机系统及APP兼容性大幅提升 -4. 完美运行Google服务 -5. 兼容最新Android P(9.0) +1. 兼容最新Android Q +2、不易被杀毒软件误报 +3. 框架优化,性能大幅提升 +4. 手机系统及APP兼容性大幅提升 +5. 完美运行Google服务 6. 支持运行纯64位App 7. 支持Dalvik和Art的Java Hook(API同Xposed) 8. 增加定位模拟代码 @@ -25,14 +25,13 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 授权说明 ------ -罗盒科技在深圳及山东设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` +罗盒科技在深圳、上海及山东设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
负责人:张总
手机:130-321-77777
QQ/微信:10890
-Company Email: Lody@aluohe.com

严重声明 From 6db6a7c11217c0c9797a22c23829de962e9952b7 Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Mar 2019 12:59:42 +0800 Subject: [PATCH 118/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index bb194c4c2..3eb3a9b6c 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -11,7 +11,7 @@ VA目前被广泛应用于`插件化开发、无感知热更新、云控自动 **Github上代码**已在2017年12月份**停止更新**,商业版代码在持续更新中,并有以下提升: 1. 兼容最新Android Q -2、不易被杀毒软件误报 +2. 不易被杀毒软件误报 3. 框架优化,性能大幅提升 4. 手机系统及APP兼容性大幅提升 5. 完美运行Google服务 From 1667c4ed427ef5c0bd060c99864078f7f49e4ef0 Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Mar 2019 13:01:11 +0800 Subject: [PATCH 119/334] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46cf1d4e4..d01ecc0ff 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ The code on Github has been updated since December 2017. The commercial version 2. Framework optimization and performance improvement 3. Compatibility of mobile phone system and APP has been greatly improved 4. Run Google services perfectly -5. Compatibility with the latest Android P (9.0) -Support running 64-bit App +5. Compatibility with the latest Android Q (10.0) +6. Support running 64-bit App 7. Java Hook that supports Dalvik and Art (API and Xposed) 8. Add positioning simulation code 9. Add the machine changing code @@ -25,7 +25,7 @@ Support running 64-bit App Authorization Note ------------------ -Luohe Technology has set up companies in Shenzhen and Shandong. From 2015 to 2018, it applied for many VirtualApp intellectual property rights, which are protected by the Intellectual Property Law of the People's Republic of China. When you need to use the VirtualApp code on Github, please purchase the commercial license. After obtaining the commercial license, you will receive the full source code of the commercial version of VirtualApp provided by us. Dozens of authorized customers pay for the use of VirtualApp commercial code, and the number of APPs that integrate VirtualApp code starts more than 200 million times a day. Thousands of Android engineers provide us with user feedback in different scenarios, and VirtualApp commercial version code has become increasingly sophisticated through the continuous efforts of our technical team to optimize. After you get the authorization, you will become one of them and enjoy the fruits of continuous iteration and improvement. And we can cooperate with our authorized customers in operation, technology and business. +Luohe Technology has set up companies in Shanghai, Shenzhen and Shandong. From 2015 to 2018, it applied for many VirtualApp intellectual property rights, which are protected by the Intellectual Property Law of the People's Republic of China. When you need to use the VirtualApp code on Github, please purchase the commercial license. After obtaining the commercial license, you will receive the full source code of the commercial version of VirtualApp provided by us. Dozens of authorized customers pay for the use of VirtualApp commercial code, and the number of APPs that integrate VirtualApp code starts more than 200 million times a day. Thousands of Android engineers provide us with user feedback in different scenarios, and VirtualApp commercial version code has become increasingly sophisticated through the continuous efforts of our technical team to optimize. After you get the authorization, you will become one of them and enjoy the fruits of continuous iteration and improvement. And we can cooperate with our authorized customers in operation, technology and business. Person in charge: General Zhang
From 00f7a30dce5e5373f0e39284a5d979578fd48cb4 Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Mar 2019 13:05:34 +0800 Subject: [PATCH 120/334] Update CHINESE.md --- CHINESE.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 3eb3a9b6c..8785844e8 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -41,9 +41,15 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +** -**2018年1月1日至2018年2月28号商业版代码更新内容** +**2019年 3月15号 最新一期更新内容** +189、修复多开时app间可能存在广播namespace冲突的BUG
+190、采用新的策略绕过Android P以后的Hidden Policy API
+191、适配Android Q(beta1) + +**2018年 1月1日 至 2019年 1月1日 商业版代码更新内容** 188、修复华为设备部分app无法识别存储的问题
187、修复启动进程可能失败导致app无法运行的问题
186、修复4.4设备部分native符号无法找到的问题
@@ -51,11 +57,6 @@ QQ/微信:10890
184、修复Service细节处理的问题
183、优化启动速度
182、修复WebView在少数机型加载失败的情况
- - -**2018年1月1日至2018年12月13号商业版代码更新内容** - -182、修复WebView在少数机型加载失败的情况
181、修复Lib决策的问题
180、修复部分华为机型无法读取内存卡的问题
179、修复Service可能存在的问题
From 99e7ccf34c41b93b560ebd2974c30a854d19b27d Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Mar 2019 13:06:29 +0800 Subject: [PATCH 121/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 8785844e8..04111df8a 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -46,7 +46,7 @@ QQ/微信:10890
**2019年 3月15号 最新一期更新内容** 189、修复多开时app间可能存在广播namespace冲突的BUG
190、采用新的策略绕过Android P以后的Hidden Policy API
-191、适配Android Q(beta1) +191、适配Android Q(beta1)
**2018年 1月1日 至 2019年 1月1日 商业版代码更新内容** From 8c01003a47d5872b2e93fc1a2dc798f4a66bd675 Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Mar 2019 13:07:37 +0800 Subject: [PATCH 122/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 04111df8a..9c2a87b95 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -41,7 +41,6 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -** **2019年 3月15号 最新一期更新内容** 189、修复多开时app间可能存在广播namespace冲突的BUG
@@ -50,6 +49,7 @@ QQ/微信:10890
**2018年 1月1日 至 2019年 1月1日 商业版代码更新内容** + 188、修复华为设备部分app无法识别存储的问题
187、修复启动进程可能失败导致app无法运行的问题
186、修复4.4设备部分native符号无法找到的问题
From 3e763b914a22a2e32ead416abf7b6170b2eae974 Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Mar 2019 13:08:02 +0800 Subject: [PATCH 123/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 9c2a87b95..9cd22d19c 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -43,6 +43,7 @@ QQ/微信:10890
**2019年 3月15号 最新一期更新内容** + 189、修复多开时app间可能存在广播namespace冲突的BUG
190、采用新的策略绕过Android P以后的Hidden Policy API
191、适配Android Q(beta1)
From ebac3bc6142ece1eee0f7a0e17031196257159d1 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 25 Apr 2019 20:25:44 +0800 Subject: [PATCH 124/334] Update CHINESE.md --- CHINESE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 9cd22d19c..6e8a445a0 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -42,6 +42,15 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019 年 4月 25 号 最新一期更新内容** + +192、修复快手无法登陆 +193、修复 YY 无法启动,更好的兼容插件化框架 +194、修复 Facebook 登陆 +195、修复 Google Play 下载的 App 无法找到 so 的问题(皇室战争) +196、修复 split apk 支持 +197、修复 Youtube 无法启动 + **2019年 3月15号 最新一期更新内容** 189、修复多开时app间可能存在广播namespace冲突的BUG
From ca6dc75b0f165a296af967ee465a6d158b6f3dd5 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 25 Apr 2019 20:27:07 +0800 Subject: [PATCH 125/334] Update CHINESE.md --- CHINESE.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 6e8a445a0..8da80562c 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -42,16 +42,16 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019 年 4月 25 号 最新一期更新内容** +**2019年 4月25号 商业版代码更新内容** -192、修复快手无法登陆 -193、修复 YY 无法启动,更好的兼容插件化框架 -194、修复 Facebook 登陆 -195、修复 Google Play 下载的 App 无法找到 so 的问题(皇室战争) -196、修复 split apk 支持 -197、修复 Youtube 无法启动 +192、修复快手无法登陆
+193、修复 YY 无法启动,更好的兼容插件化框架
+194、修复 Facebook 登陆
+195、修复 Google Play 下载的 App 无法找到 so 的问题(皇室战争)
+196、修复 split apk 支持
+197、修复 Youtube 无法启动
-**2019年 3月15号 最新一期更新内容** +**2019年 3月15号 商业版代码更新内容** 189、修复多开时app间可能存在广播namespace冲突的BUG
190、采用新的策略绕过Android P以后的Hidden Policy API
From 77047f9638b9754c12fdb328814322b79b94682d Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 25 Apr 2019 20:29:57 +0800 Subject: [PATCH 126/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 8da80562c..3d58d5c52 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -50,6 +50,7 @@ QQ/微信:10890
195、修复 Google Play 下载的 App 无法找到 so 的问题(皇室战争)
196、修复 split apk 支持
197、修复 Youtube 无法启动
+198、修复优酷无法启动的问题
**2019年 3月15号 商业版代码更新内容** From 7d7771cef7365068fd89b0233aab1dace7f6e7f3 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 9 May 2019 16:50:10 +0800 Subject: [PATCH 127/334] Update CHINESE.md --- CHINESE.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 3d58d5c52..63d76362f 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -42,25 +42,25 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 4月25号 商业版代码更新内容** +**2019年 5月9号 商业版代码更新内容** -192、修复快手无法登陆
-193、修复 YY 无法启动,更好的兼容插件化框架
-194、修复 Facebook 登陆
-195、修复 Google Play 下载的 App 无法找到 so 的问题(皇室战争)
-196、修复 split apk 支持
-197、修复 Youtube 无法启动
-198、修复优酷无法启动的问题
+202、修复配置网络证书的 App 的联网
+201、重构组件状态管理
+200、优化 MIUI/EMUI ContentProvider 兼容性
+199、修复 StorageStats Hook
-**2019年 3月15号 商业版代码更新内容** +**2018年 1月1日 至 2019年 4月25日 商业版代码更新内容** -189、修复多开时app间可能存在广播namespace冲突的BUG
+198、修复快手无法登陆
+197、修复 YY 无法启动,更好的兼容插件化框架
+196、修复 Facebook 登陆
+195、修复 Google Play 下载的 App 无法找到 so 的问题(皇室战争)
+194、修复 split apk 支持
+193、修复 Youtube 无法启动
+192、修复优酷无法启动的问题
+191、修复多开时app间可能存在广播namespace冲突的BUG
190、采用新的策略绕过Android P以后的Hidden Policy API
-191、适配Android Q(beta1)
- - -**2018年 1月1日 至 2019年 1月1日 商业版代码更新内容** - +189、适配Android Q(beta1)
188、修复华为设备部分app无法识别存储的问题
187、修复启动进程可能失败导致app无法运行的问题
186、修复4.4设备部分native符号无法找到的问题
From 98a5fcc67ea63a3266067d3dae39a7c52e0b0c39 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Sat, 11 May 2019 08:29:31 +0800 Subject: [PATCH 128/334] Update CHINESE.md --- CHINESE.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 63d76362f..af515e2c4 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -49,8 +49,8 @@ QQ/微信:10890
200、优化 MIUI/EMUI ContentProvider 兼容性
199、修复 StorageStats Hook
-**2018年 1月1日 至 2019年 4月25日 商业版代码更新内容** - +

+**2018年 1月1日 至 2019年 4月25日 商业版代码更新内容** 198、修复快手无法登陆
197、修复 YY 无法启动,更好的兼容插件化框架
196、修复 Facebook 登陆
@@ -249,4 +249,7 @@ QQ/微信:10890
3、解决了微信被封的一些问题
2、修复了部分机型兼容性
1、修复了12个小BUG
+
+ + From 4d2aa8e0a502f4699bd232254fa990b540ada90b Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Sat, 11 May 2019 08:30:21 +0800 Subject: [PATCH 129/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index af515e2c4..a5112d6d0 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -50,7 +50,7 @@ QQ/微信:10890
199、修复 StorageStats Hook
-**2018年 1月1日 至 2019年 4月25日 商业版代码更新内容** +2018年 1月1日 至 2019年 4月25日 商业版代码更新内容(下拉打开) 198、修复快手无法登陆
197、修复 YY 无法启动,更好的兼容插件化框架
196、修复 Facebook 登陆
From cc104d639ea1f67ed2679c301b72875cd5976acf Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Mon, 13 May 2019 10:40:13 +0800 Subject: [PATCH 130/334] Update CHINESE.md --- CHINESE.md | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index a5112d6d0..5a22f4efc 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -2,11 +2,80 @@ 项目简介 --- -VirtualApp是由`罗盒科技`开发并运营的商业项目,VirtualApp在你的App内创建一个`虚拟空间`,你可以在虚拟空间内任意的`安装`、`启动`和`卸载`APK,这一切都与外部隔离,如同一个`沙盒`。 +VirtualApp(以下简称:VA)是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。其产品形态为高可扩展,可定制的集成SDK,您可以基于VA或者使用VA定制开发各种看似不可能完成的项目。VA目前被广泛应用于插件化开发、无感知热更新、云控自动化、多开、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府保密、手机模拟信息、脚本自动化、自动化测试等技术领域。 -运行在`VA`中的APK无需在外部安装,即VA支持**免安装运行APK**。 +VA的特有能力 +--- + +- 克隆能力 +可以克隆外部系统中已经安装的App,并在内部运行,互不干扰。典型应用场景为App双开。 + +- 免安装能力 +除了克隆已安装之外,VA可以直接在内部安装(外部无感知)apk,并在内部直接运行。典型应用场景为插件化,独立应用市场等。 + +- 多开能力 +VA不仅可以“双开”,独特的多用户模式支持用户在内部无限多开同一个App。 + +- 内外隔离能力 +VA是一个标准的沙盒,或者说“虚拟机”,提供了一整套内部与外部的隔离机制,包括但不限于(文件隔离/组件隔离/进程通讯隔离),简单的说VA内部就是一个“完全独立的空间”。在此基础之上,稍作定制即可实现一部手机上的“虚拟手机”。当然您也可以发挥想象,定制成应用于数据加密,数据隔离,隐私保护,企业管理的应用系统。 + +- 对于内部App的完全控制能力 +VA对于内部的App具有完全的监控和控制能力,这点在未Root的外部环境中是绝对无法实现的。 +
+详细(下拉打开) +1. 服务请求控制,首先VA直接提供了一些服务请求的拦截,您可以在集成VA的时候方便的定制这些服务请求,包括但远不限于(App请求安装apk/App请求打开某些文件/App请求定位数据/App请求手机信息等等) +2. 系统API控制,VA虚拟并实现了整个安卓系统框架,这也是VA可以免安装在内部运行apk的原理,您可以对虚拟框架的实现进行修改以动态监测分析App的行为等;除此之外,您还可模拟一些系统行为以实现一些在外部难以实现的需求(例如游戏手柄)。 +3. 内存读写,VA可以无需Root读写内部App进程的内存。 +4. 免Root调试,VA可以免Root调试(ptrace)内部的App进程,基于此您还可以实现免Root的进程注入。 +5. 加载任意“插件”和“行为”,VA内部的App进程由VA的框架Client端代码派生而来,所以您可以在进程的入口代码插入任何“加载”以及“控制”逻辑。这些实现都非常简单。 +6. 方法Hook,VA内置了一套运行于Android各个版本(直到AndroidQ)的Xposed框架以及native hook框架,基于此您可以方便的Hook任意内部App的任意Java/Native方法。可以轻松实现一个免Root的Xposed环境(有实例代码)。 +7. 文件控制,VA内置了完整的文件重定向,可以方便的控制内部App的文件的读写,基于此可以实现对文件的保护加密等功能。 +8. 注:以上控制能力均有实现代码或者实例以作参考。 +
+ + +VA的其他特性 +--- + +- 高性能 +进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 + +- 全版本支持 +支持4.1-10.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 + +- 支持Google服务 +提供Google服务的支持,以支持海外的App + +VA实例 +--- + +- APP多开 +游戏多开,微信多开等 + +- 游戏租号 +一键上号,一键登陆,免去用户频繁输入账号密码 + +- Xposed +免Root实现Xposed环境 + +- 谷歌空间 +免去国产手机无法使用谷歌服务的烦恼,一键安装使用谷歌应用 + +- 游戏手柄 +免Root方便的使用手柄映射 + +- 游戏中心 +免安装运行游戏,多开游戏,游戏内屏录制,统一的游戏更新管理,投射游戏画面到电视。 + +- 游戏自动化 + +- 军政安全: +文件隔离/组件隔离/进程通讯隔离/加密监控等等 + + + +**现在开始使用VA发挥你的想象力吧!** -VA目前被广泛应用于`插件化开发、无感知热更新、云控自动化、多开、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府保密、手机模拟信息、脚本自动化、自动化测试`等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能-----这都取决于您的想象力。 **Github上代码**已在2017年12月份**停止更新**,商业版代码在持续更新中,并有以下提升: From b3be927754878c31943452ee83c7b0ff4e759114 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Mon, 13 May 2019 10:42:16 +0800 Subject: [PATCH 131/334] Update CHINESE.md --- CHINESE.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 5a22f4efc..84932751a 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -7,69 +7,69 @@ VirtualApp(以下简称:VA)是一款运行于Android系统的沙盒产品, VA的特有能力 --- -- 克隆能力 +- 克隆能力
可以克隆外部系统中已经安装的App,并在内部运行,互不干扰。典型应用场景为App双开。 -- 免安装能力 +- 免安装能力
除了克隆已安装之外,VA可以直接在内部安装(外部无感知)apk,并在内部直接运行。典型应用场景为插件化,独立应用市场等。 -- 多开能力 +- 多开能力
VA不仅可以“双开”,独特的多用户模式支持用户在内部无限多开同一个App。 -- 内外隔离能力 +- 内外隔离能力
VA是一个标准的沙盒,或者说“虚拟机”,提供了一整套内部与外部的隔离机制,包括但不限于(文件隔离/组件隔离/进程通讯隔离),简单的说VA内部就是一个“完全独立的空间”。在此基础之上,稍作定制即可实现一部手机上的“虚拟手机”。当然您也可以发挥想象,定制成应用于数据加密,数据隔离,隐私保护,企业管理的应用系统。 -- 对于内部App的完全控制能力 +- 对于内部App的完全控制能力
VA对于内部的App具有完全的监控和控制能力,这点在未Root的外部环境中是绝对无法实现的。
详细(下拉打开) -1. 服务请求控制,首先VA直接提供了一些服务请求的拦截,您可以在集成VA的时候方便的定制这些服务请求,包括但远不限于(App请求安装apk/App请求打开某些文件/App请求定位数据/App请求手机信息等等) -2. 系统API控制,VA虚拟并实现了整个安卓系统框架,这也是VA可以免安装在内部运行apk的原理,您可以对虚拟框架的实现进行修改以动态监测分析App的行为等;除此之外,您还可模拟一些系统行为以实现一些在外部难以实现的需求(例如游戏手柄)。 -3. 内存读写,VA可以无需Root读写内部App进程的内存。 -4. 免Root调试,VA可以免Root调试(ptrace)内部的App进程,基于此您还可以实现免Root的进程注入。 -5. 加载任意“插件”和“行为”,VA内部的App进程由VA的框架Client端代码派生而来,所以您可以在进程的入口代码插入任何“加载”以及“控制”逻辑。这些实现都非常简单。 -6. 方法Hook,VA内置了一套运行于Android各个版本(直到AndroidQ)的Xposed框架以及native hook框架,基于此您可以方便的Hook任意内部App的任意Java/Native方法。可以轻松实现一个免Root的Xposed环境(有实例代码)。 -7. 文件控制,VA内置了完整的文件重定向,可以方便的控制内部App的文件的读写,基于此可以实现对文件的保护加密等功能。 -8. 注:以上控制能力均有实现代码或者实例以作参考。 + 1. 服务请求控制,首先VA直接提供了一些服务请求的拦截,您可以在集成VA的时候方便的定制这些服务请求,包括但远不限于(App请求安装apk/App请求打开某些文件/App请求定位数据/App请求手机信息等等)
+ 2. 系统API控制,VA虚拟并实现了整个安卓系统框架,这也是VA可以免安装在内部运行apk的原理,您可以对虚拟框架的实现进行修改以动态监测分析App的行为等;除此之外,您还可模拟一些系统行为以实现一些在外部难以实现的需求(例如游戏手柄)。
+ 3. 内存读写,VA可以无需Root读写内部App进程的内存。
+ 4. 免Root调试,VA可以免Root调试(ptrace)内部的App进程,基于此您还可以实现免Root的进程注入。
+ 5. 加载任意“插件”和“行为”,VA内部的App进程由VA的框架Client端代码派生而来,所以您可以在进程的入口代码插入任何“加载”以及“控制”逻辑。这些实现都非常简单。
+ 6. 方法Hook,VA内置了一套运行于Android各个版本(直到AndroidQ)的Xposed框架以及native hook框架,基于此您可以方便的Hook任意内部App的任意Java/Native方法。可以轻松实现一个免Root的Xposed环境(有实例代码)。
+ 7. 文件控制,VA内置了完整的文件重定向,可以方便的控制内部App的文件的读写,基于此可以实现对文件的保护加密等功能。
+ 8. 注:以上控制能力均有实现代码或者实例以作参考。
VA的其他特性 --- -- 高性能 +- 高性能
进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 -- 全版本支持 +- 全版本支持
支持4.1-10.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 -- 支持Google服务 +- 支持Google服务
提供Google服务的支持,以支持海外的App VA实例 --- -- APP多开 +- APP多开
游戏多开,微信多开等 -- 游戏租号 +- 游戏租号
一键上号,一键登陆,免去用户频繁输入账号密码 -- Xposed +- Xposed
免Root实现Xposed环境 -- 谷歌空间 +- 谷歌空间
免去国产手机无法使用谷歌服务的烦恼,一键安装使用谷歌应用 -- 游戏手柄 +- 游戏手柄
免Root方便的使用手柄映射 -- 游戏中心 +- 游戏中心
免安装运行游戏,多开游戏,游戏内屏录制,统一的游戏更新管理,投射游戏画面到电视。 -- 游戏自动化 +- 游戏自动化
-- 军政安全: +- 军政安全
文件隔离/组件隔离/进程通讯隔离/加密监控等等 From bf4011f2cc059510fc9ef171d841a9dd497c9442 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Mon, 13 May 2019 11:08:19 +0800 Subject: [PATCH 132/334] Update CHINESE.md --- CHINESE.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 84932751a..b6d928d20 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -23,13 +23,13 @@ VA是一个标准的沙盒,或者说“虚拟机”,提供了一整套内部 VA对于内部的App具有完全的监控和控制能力,这点在未Root的外部环境中是绝对无法实现的。
详细(下拉打开) - 1. 服务请求控制,首先VA直接提供了一些服务请求的拦截,您可以在集成VA的时候方便的定制这些服务请求,包括但远不限于(App请求安装apk/App请求打开某些文件/App请求定位数据/App请求手机信息等等)
- 2. 系统API控制,VA虚拟并实现了整个安卓系统框架,这也是VA可以免安装在内部运行apk的原理,您可以对虚拟框架的实现进行修改以动态监测分析App的行为等;除此之外,您还可模拟一些系统行为以实现一些在外部难以实现的需求(例如游戏手柄)。
- 3. 内存读写,VA可以无需Root读写内部App进程的内存。
- 4. 免Root调试,VA可以免Root调试(ptrace)内部的App进程,基于此您还可以实现免Root的进程注入。
- 5. 加载任意“插件”和“行为”,VA内部的App进程由VA的框架Client端代码派生而来,所以您可以在进程的入口代码插入任何“加载”以及“控制”逻辑。这些实现都非常简单。
- 6. 方法Hook,VA内置了一套运行于Android各个版本(直到AndroidQ)的Xposed框架以及native hook框架,基于此您可以方便的Hook任意内部App的任意Java/Native方法。可以轻松实现一个免Root的Xposed环境(有实例代码)。
- 7. 文件控制,VA内置了完整的文件重定向,可以方便的控制内部App的文件的读写,基于此可以实现对文件的保护加密等功能。
+ 1. 服务请求控制,首先VA直接提供了一些服务请求的拦截,您可以在集成VA的时候方便的定制这些服务请求,包括但远不限于(App请求安装apk/App请求打开某些文件/App请求定位数据/App请求手机信息等等)

+ 2. 系统API控制,VA虚拟并实现了整个安卓系统框架,这也是VA可以免安装在内部运行apk的原理,您可以对虚拟框架的实现进行修改以动态监测分析App的行为等;除此之外,您还可模拟一些系统行为以实现一些在外部难以实现的需求(例如游戏手柄)。

+ 3. 内存读写,VA可以无需Root读写内部App进程的内存。

+ 4. 免Root调试,VA可以免Root调试(ptrace)内部的App进程,基于此您还可以实现免Root的进程注入。

+ 5. 加载任意“插件”和“行为”,VA内部的App进程由VA的框架Client端代码派生而来,所以您可以在进程的入口代码插入任何“加载”以及“控制”逻辑。这些实现都非常简单。

+ 6. 方法Hook,VA内置了一套运行于Android各个版本(直到AndroidQ)的Xposed框架以及native hook框架,基于此您可以方便的Hook任意内部App的任意Java/Native方法。可以轻松实现一个免Root的Xposed环境(有实例代码)。

+ 7. 文件控制,VA内置了完整的文件重定向,可以方便的控制内部App的文件的读写,基于此可以实现对文件的保护加密等功能。

8. 注:以上控制能力均有实现代码或者实例以作参考。
@@ -68,6 +68,7 @@ VA实例 免安装运行游戏,多开游戏,游戏内屏录制,统一的游戏更新管理,投射游戏画面到电视。 - 游戏自动化
+方便的模拟用户操作 - 军政安全
文件隔离/组件隔离/进程通讯隔离/加密监控等等 From a87f821c74d51c044388cdb3a412dca4729ae884 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Mon, 13 May 2019 11:09:30 +0800 Subject: [PATCH 133/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index b6d928d20..9c62e9fde 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -68,7 +68,7 @@ VA实例 免安装运行游戏,多开游戏,游戏内屏录制,统一的游戏更新管理,投射游戏画面到电视。 - 游戏自动化
-方便的模拟用户操作 +方便地模拟用户操作 - 军政安全
文件隔离/组件隔离/进程通讯隔离/加密监控等等 From 3ac7e939d5a8b317bff1ef67aec2dfbe0b73cd84 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 16 May 2019 16:23:13 +0800 Subject: [PATCH 134/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 9c62e9fde..23172546f 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -104,6 +104,12 @@ VA实例 QQ/微信:10890

+需求定制 +------ + +罗盒科技提供基于VA的需求咨询与功能开发定制,即使您不懂技术,也可以根据您的需求为您定制成品。 + + 严重声明 ------ From e966d9ad2ec83c930ce2d131f834f4d0b56d250f Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 17 May 2019 11:49:06 +0800 Subject: [PATCH 135/334] Update CHINESE.md --- CHINESE.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 23172546f..47628642a 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -43,6 +43,9 @@ VA的其他特性 - 全版本支持
支持4.1-10.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 +- 易扩展与集成
+VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 + - 支持Google服务
提供Google服务的支持,以支持海外的App @@ -52,6 +55,12 @@ VA实例 - APP多开
游戏多开,微信多开等 +- 虚拟手机
+在已有的手机上虚拟出一部专用手机,企业单位可以进行监控管理 + +- 安全空间
+独立空间,内外隔离,保证内部的私密与安全 + - 游戏租号
一键上号,一键登陆,免去用户频繁输入账号密码 @@ -118,8 +127,10 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 5月9号 商业版代码更新内容** +**2019年 5月17号 商业版代码更新内容** +204、修复了货拉拉无法安装的问题
+203、优化了64位apk的判定逻辑
202、修复配置网络证书的 App 的联网
201、重构组件状态管理
200、优化 MIUI/EMUI ContentProvider 兼容性
From bdae0660d90d5fa9b5be2de5b6035eafc5836165 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 17 May 2019 14:15:32 +0800 Subject: [PATCH 136/334] Update README.md --- README.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d01ecc0ff..d6ca75b37 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Luohe Technology has set up companies in Shanghai, Shenzhen and Shandong. From 2 Person in charge: General Zhang
Mobile: +86 1303217777 7
Wechat: 10890
-Company email: Lody@aluohe.com +Company email: zl@aluohe.com Strictness Disclaimer @@ -39,6 +39,33 @@ Strictness Disclaimer If you use VirtualApp for internal use, commercial profit or upload to the application market without authorization, we will directly collect evidence and report to the police (copyright infringement) or prosecute, which will cause criminal liability and legal proceedings to your company and affect your company's goodwill and investment. Buying a commercial license saves you a lot of development, testing, and refining time, allowing you more time to innovate and monetize. + + +**The updating contents of commercial version code from December 13, 2018 to May 17, 2019** + +204、Fix install of Huolala
+203、Fix check logic for 64bit apk
+202、Support NetworkSecurityConfig
+201、Rewrite Component State Manager
+200、Optimaize compatibility of MIUI/EMUI ContentProvider
+199、Fix StorageStats Hook
+198、Fix login of Kuishou
+197、Fix support of some plugin framework(Small, Atlas)
+196、Fix login of Facebook
+195、Fix so load error of some app download from Google Play(COC)
+194、Fix suppport for split apk
+193、Fix crash of Youtube
+192、Fix crash of Youku
+191、Fix conflict of broadcast namespace
+190、Add a new policy to bypass Hidden Policy API above Android P
+189、Pre support Android Q(beta1)
+188、Fix access to SD Card in some huawei devices
+187、Fix some launch process failure
+186、Fix get native symbol failure in some 4.4 devices
+185、Fix got package name failure by WebView in some devices
+184、Fix detail of service
+183、Optimize launch speed
+ The updating contents of commercial version code from January 1, 2018 to December 13, 2018. 182. Fix WebView loading failure in a few models
From 7e03716e7dc6c678a5bff3c0c25a822e04c96ffb Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 17 May 2019 14:16:43 +0800 Subject: [PATCH 137/334] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d6ca75b37..83f2aeb33 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ If you use VirtualApp for internal use, commercial profit or upload to the appli 201、Rewrite Component State Manager
200、Optimaize compatibility of MIUI/EMUI ContentProvider
199、Fix StorageStats Hook
-198、Fix login of Kuishou
-197、Fix support of some plugin framework(Small, Atlas)
+198、Fix login of Kuaishou
+197、Fix support for some plugin frameworks(Small, Atlas)
196、Fix login of Facebook
195、Fix so load error of some app download from Google Play(COC)
194、Fix suppport for split apk
@@ -58,7 +58,7 @@ If you use VirtualApp for internal use, commercial profit or upload to the appli 192、Fix crash of Youku
191、Fix conflict of broadcast namespace
190、Add a new policy to bypass Hidden Policy API above Android P
-189、Pre support Android Q(beta1)
+189、Pre support for Android Q(beta1)
188、Fix access to SD Card in some huawei devices
187、Fix some launch process failure
186、Fix get native symbol failure in some 4.4 devices
From 5b3caa4982d76715e04fac6234ca7e786e4687d1 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 17 May 2019 14:18:19 +0800 Subject: [PATCH 138/334] Update README.md --- README.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 83f2aeb33..872be8b7c 100644 --- a/README.md +++ b/README.md @@ -43,28 +43,28 @@ If you use VirtualApp for internal use, commercial profit or upload to the appli **The updating contents of commercial version code from December 13, 2018 to May 17, 2019** -204、Fix install of Huolala
-203、Fix check logic for 64bit apk
-202、Support NetworkSecurityConfig
-201、Rewrite Component State Manager
-200、Optimaize compatibility of MIUI/EMUI ContentProvider
-199、Fix StorageStats Hook
-198、Fix login of Kuaishou
-197、Fix support for some plugin frameworks(Small, Atlas)
-196、Fix login of Facebook
-195、Fix so load error of some app download from Google Play(COC)
-194、Fix suppport for split apk
-193、Fix crash of Youtube
-192、Fix crash of Youku
-191、Fix conflict of broadcast namespace
-190、Add a new policy to bypass Hidden Policy API above Android P
-189、Pre support for Android Q(beta1)
-188、Fix access to SD Card in some huawei devices
-187、Fix some launch process failure
-186、Fix get native symbol failure in some 4.4 devices
-185、Fix got package name failure by WebView in some devices
-184、Fix detail of service
-183、Optimize launch speed
+204. Fix install of Huolala
+203. Fix check logic for 64bit apk
+202. Support NetworkSecurityConfig
+201. Rewrite Component State Manager
+200. Optimaize compatibility of MIUI/EMUI ContentProvider
+199. Fix StorageStats Hook
+198. Fix login of Kuaishou
+197. Fix support for some plugin frameworks(Small, Atlas)
+196. Fix login of Facebook
+195. Fix so load error of some app download from Google Play(COC)
+194. Fix suppport for split apk
+193. Fix crash of Youtube
+192. Fix crash of Youku
+191. Fix conflict of broadcast namespace
+190. Add a new policy to bypass Hidden Policy API above Android P
+189. Pre support for Android Q(beta1)
+188. Fix access to SD Card in some huawei devices
+187. Fix some launch process failure
+186. Fix get native symbol failure in some 4.4 devices
+185. Fix got package name failure by WebView in some devices
+184. Fix detail of service
+183. Optimize launch speed
The updating contents of commercial version code from January 1, 2018 to December 13, 2018. From 809096609eee419523449a6e430664f37e92431e Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Mon, 10 Jun 2019 17:24:25 +0800 Subject: [PATCH 139/334] Update CHINESE.md --- CHINESE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 47628642a..09d2e6de1 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -127,8 +127,9 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 5月17号 商业版代码更新内容** +**2019年 6月10号 商业版代码更新内容** +205、适配到 Android Q beta3
204、修复了货拉拉无法安装的问题
203、优化了64位apk的判定逻辑
202、修复配置网络证书的 App 的联网
From fa4c1bc536d33ebb9e34ee15dff6cac88262fca5 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 13 Jun 2019 19:29:55 +0800 Subject: [PATCH 140/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 09d2e6de1..b6dcab7c5 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -129,6 +129,7 @@ QQ/微信:10890
**2019年 6月10号 商业版代码更新内容** +206、初步支持纯64位模式,以应对8月份的谷歌市场的策略变化
205、适配到 Android Q beta3
204、修复了货拉拉无法安装的问题
203、优化了64位apk的判定逻辑
From 3a38cae4d741a1e9c606fdda91c208eda1d732ce Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 14 Jun 2019 11:26:08 +0800 Subject: [PATCH 141/334] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 872be8b7c..076de4143 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,10 @@ If you use VirtualApp for internal use, commercial profit or upload to the appli -**The updating contents of commercial version code from December 13, 2018 to May 17, 2019** +**The updating contents of commercial version code from December 13, 2018 to June 13, 2019** +206. Preliminary support for pure 64-bit mode to meet the requirements of the Google Market
+205. Preliminary support for Android Q beta4
204. Fix install of Huolala
203. Fix check logic for 64bit apk
202. Support NetworkSecurityConfig
From c469abe9716a4fdf4f728261a5b3d5dcc4bc9fef Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Sun, 30 Jun 2019 09:37:51 +0800 Subject: [PATCH 142/334] Update CHINESE.md --- CHINESE.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index b6dcab7c5..8bb373607 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -127,19 +127,25 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 6月10号 商业版代码更新内容** - +**2019年 6月30号 商业版代码更新内容** + +212、修复从宿主向插件发送广播的方法
+211、兼容最新版 gradle 插件
+210、增加广播命名空间以避免多个使用 VA 技术的 App 互相干扰
+209、修复 IMO 打不开的问题
+208、修复部分 ContentProvider 找不到的问题
+207、支持纯32位模式,以兼容老设备
206、初步支持纯64位模式,以应对8月份的谷歌市场的策略变化
-205、适配到 Android Q beta3
+205、适配到 Android Q beta4
+ +
+2018年 1月1日 至 2019年 6月 10 日 商业版代码更新内容(下拉打开) 204、修复了货拉拉无法安装的问题
203、优化了64位apk的判定逻辑
202、修复配置网络证书的 App 的联网
201、重构组件状态管理
200、优化 MIUI/EMUI ContentProvider 兼容性
199、修复 StorageStats Hook
- -
-2018年 1月1日 至 2019年 4月25日 商业版代码更新内容(下拉打开) 198、修复快手无法登陆
197、修复 YY 无法启动,更好的兼容插件化框架
196、修复 Facebook 登陆
@@ -341,4 +347,3 @@ QQ/微信:10890
- From b3a1649ea5554b26ae5d5ab0e2063d4b6a4984ca Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Sun, 28 Jul 2019 20:59:32 +0800 Subject: [PATCH 143/334] Update CHINESE.md --- CHINESE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 8bb373607..068472253 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -127,8 +127,10 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 6月30号 商业版代码更新内容** +**2019年 7月30号 商业版代码更新内容** +214、改进 App 层提示信息
+213、改进部分编码
212、修复从宿主向插件发送广播的方法
211、兼容最新版 gradle 插件
210、增加广播命名空间以避免多个使用 VA 技术的 App 互相干扰
From 930eceda73d70da11aefaaa12d7fe1e80de9baba Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 20 Aug 2019 11:17:18 +0800 Subject: [PATCH 144/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 068472253..e5c134775 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -104,7 +104,7 @@ VA实例 授权说明 ------ -罗盒科技在深圳、上海及山东设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` +罗盒科技在上海及山东济宁设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
From 347742661a52e7148e2f1519627eed7a6efcaa88 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 20 Aug 2019 11:19:22 +0800 Subject: [PATCH 145/334] Update CHINESE.md --- CHINESE.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index e5c134775..5e8494351 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -113,11 +113,6 @@ VA实例 QQ/微信:10890

-需求定制 ------- - -罗盒科技提供基于VA的需求咨询与功能开发定制,即使您不懂技术,也可以根据您的需求为您定制成品。 - 严重声明 ------ From 2be9379d79f0bf14c7ea599c9a79aa422208575e Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 22 Aug 2019 17:22:36 +0800 Subject: [PATCH 146/334] Update CHINESE.md --- CHINESE.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 5e8494351..4f7af57e4 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -122,8 +122,12 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 7月30号 商业版代码更新内容** +**2019年 8月20号 商业版代码更新内容** +215、新增加支持32位插件的64位分支,该分支支持32位旧设备并且64位设备在32位插件的情况下可以支持32位旧应用
+ +
+2018年 1月1日 至 2019年 7月 30 日 商业版代码更新内容(下拉打开) 214、改进 App 层提示信息
213、改进部分编码
212、修复从宿主向插件发送广播的方法
@@ -134,9 +138,6 @@ QQ/微信:10890
207、支持纯32位模式,以兼容老设备
206、初步支持纯64位模式,以应对8月份的谷歌市场的策略变化
205、适配到 Android Q beta4
- -
-2018年 1月1日 至 2019年 6月 10 日 商业版代码更新内容(下拉打开) 204、修复了货拉拉无法安装的问题
203、优化了64位apk的判定逻辑
202、修复配置网络证书的 App 的联网
From adfb931b3940a8bbe14f4dff82da52a59bc7d829 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 17 Sep 2019 10:11:11 +0800 Subject: [PATCH 147/334] Update CHINESE.md --- CHINESE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 4f7af57e4..63e2527a2 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -122,8 +122,10 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 8月20号 商业版代码更新内容** +**2019年 9月16号 商业版代码更新内容** +217、初步适配 Android Q 正式版
+216、修复数个64位分支的 Bug
215、新增加支持32位插件的64位分支,该分支支持32位旧设备并且64位设备在32位插件的情况下可以支持32位旧应用
From e6d097eed4c0ea88168f2f28ce19b7965a548c19 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 20 Sep 2019 13:55:46 +0800 Subject: [PATCH 148/334] Update CHINESE.md --- CHINESE.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 63e2527a2..f410afa8e 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -124,6 +124,10 @@ QQ/微信:10890
**2019年 9月16号 商业版代码更新内容** +221、修复安装在扩展插件中的 apk 无法正确显示图标和名称的问题
+220、修复 twitter 无法打开的问题
+219、正式兼容 Android Q 正式版!
+218、修复 Android Q 某些 Activity 无法再次打开的问题
217、初步适配 Android Q 正式版
216、修复数个64位分支的 Bug
215、新增加支持32位插件的64位分支,该分支支持32位旧设备并且64位设备在32位插件的情况下可以支持32位旧应用
From 9f6a4602740932575189e81d03b03629678c9be6 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 20 Sep 2019 13:56:31 +0800 Subject: [PATCH 149/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index f410afa8e..86810e630 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -122,7 +122,7 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2019年 9月16号 商业版代码更新内容** +**2019年 9月20号 商业版代码更新内容** 221、修复安装在扩展插件中的 apk 无法正确显示图标和名称的问题
220、修复 twitter 无法打开的问题
From b2b76041db48ac27c264bbe5983c7411a0226c47 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 8 Oct 2019 17:16:57 +0800 Subject: [PATCH 150/334] Update CHINESE.md --- CHINESE.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 86810e630..8b53e1b3b 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,8 +121,12 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 10月8号 商业版代码更新内容** -**2019年 9月20号 商业版代码更新内容** +223、修复Android P 以上内部 app 返回桌面异常的问题
+222、64位分支支持 Android Q
+ +**2019年 9月20号 至 2019年 10月7号 商业版代码更新内容** 221、修复安装在扩展插件中的 apk 无法正确显示图标和名称的问题
220、修复 twitter 无法打开的问题
From 1ae59eb97c5cc133bdc6bc034ef3c93d0a1e6215 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 24 Oct 2019 16:11:32 +0800 Subject: [PATCH 151/334] Update CHINESE.md --- CHINESE.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 8b53e1b3b..31e7a7f29 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,13 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 10月8号 至 2019年 10月24号 商业版代码更新内容** + +227、修复 Android P 下 AppOspManager 的异常
+226、添加 Android P 下 ActivityTaskManager 丢失的 Hook
+225、修复 Android P 下 Activity Top Resume 异常
+224、支持在系统多用户模式下运行!
+ **2019年 10月8号 商业版代码更新内容** 223、修复Android P 以上内部 app 返回桌面异常的问题
From 4714c51eb1379814df53f7c7cdd9dfa76518e040 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 1 Nov 2019 10:55:06 +0800 Subject: [PATCH 152/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 31e7a7f29..b3b450d21 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,12 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 10月25号 至 2019年 11月1号 商业版代码更新内容** + +230、修复克隆 Google Play 下载的 64位 App
+229、修复企业微信
+228、修复 Telegram
+ **2019年 10月8号 至 2019年 10月24号 商业版代码更新内容** 227、修复 Android P 下 AppOspManager 的异常
From 75a144781035252a73c38f19fc25d99be1ea49ef Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 8 Nov 2019 12:00:02 +0800 Subject: [PATCH 153/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index b3b450d21..401589087 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,12 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 11月2号 至 2019年 11月8号 商业版代码更新内容** + +233、修复 WPS, 网易邮箱等在 Q 设备上崩溃的问题
+232、修复汤姆猫跑酷在部分 Q 设备上崩溃的问题
+231、修复 QQ 在部分 Q 设备上崩溃的问题
+ **2019年 10月25号 至 2019年 11月1号 商业版代码更新内容** 230、修复克隆 Google Play 下载的 64位 App
From 5fd576c608f4143b74fb1fa58a8b20c075ac6169 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 19 Nov 2019 13:25:15 +0800 Subject: [PATCH 154/334] Update CHINESE.md --- CHINESE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 401589087..d04a5977f 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,11 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 11月9号 至 2019年 11月19号 商业版代码更新内容** + +235、修复 Android 5.x 的 ART Hook
+234、修复 ART Hook 可能导致的死锁问题
+ **2019年 11月2号 至 2019年 11月8号 商业版代码更新内容** 233、修复 WPS, 网易邮箱等在 Q 设备上崩溃的问题
From b32a1160619e6ee38afabbddd765938eaa634b98 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Sat, 14 Dec 2019 11:11:59 +0800 Subject: [PATCH 155/334] Update CHINESE.md --- CHINESE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index d04a5977f..689271c2f 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,11 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 11月20号 至 2019年 12月14号 商业版代码更新内容** + +237、修复 Notification 缓存导致的崩溃
+236、修复高版本 Notification 的 classloader 问题
+ **2019年 11月9号 至 2019年 11月19号 商业版代码更新内容** 235、修复 Android 5.x 的 ART Hook
From ccf0c13047d3cbb04f31f75d70298503ba84fc2b Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Wed, 25 Dec 2019 12:13:59 +0800 Subject: [PATCH 156/334] Update CHINESE.md --- CHINESE.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 689271c2f..eda35e26d 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,13 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 12月15号 至 2019年 12月25号 商业版代码更新内容** + +241、修复 Emui10 上企业微信等 App 无法启动的问题
+240、修复在 4.x 可能导致的崩溃
+239、升级 SandHook 修复对 Thread 类的 Hook
+238、修复 Android Q 某些接口导致的权限问题
+ **2019年 11月20号 至 2019年 12月14号 商业版代码更新内容** 237、修复 Notification 缓存导致的崩溃
From 757e165b29e97ef3ced5499b417bde984e83a954 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 10 Jan 2020 11:50:04 +0800 Subject: [PATCH 157/334] Update CHINESE.md --- CHINESE.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index eda35e26d..89d57b2b8 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -108,9 +108,8 @@ VA实例
-负责人:张总
-手机:130-321-77777
-QQ/微信:10890
+商务负责人:陈总
+电话:165-021-77777(微信同号)

From c76429ac6359e8c81740d667afbb2e401974abd7 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Wed, 15 Jan 2020 00:27:08 +0800 Subject: [PATCH 158/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 89d57b2b8..8ee95a4f7 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -120,6 +120,12 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2019年 12月26号 至 2020年 1月15号 商业版代码更新内容** + +244、修复 Android Q 遗漏的 hook
+243、禁用 Emui10 的 AutoFill
+242、增加新 api 结束所有 activity
+ **2019年 12月15号 至 2019年 12月25号 商业版代码更新内容** 241、修复 Emui10 上企业微信等 App 无法启动的问题
From f917cc891571214ff46ab1a787b3598b39e9e548 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 16 Jan 2020 00:18:35 +0800 Subject: [PATCH 159/334] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 076de4143..11a3fb451 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,8 @@ Authorization Note Luohe Technology has set up companies in Shanghai, Shenzhen and Shandong. From 2015 to 2018, it applied for many VirtualApp intellectual property rights, which are protected by the Intellectual Property Law of the People's Republic of China. When you need to use the VirtualApp code on Github, please purchase the commercial license. After obtaining the commercial license, you will receive the full source code of the commercial version of VirtualApp provided by us. Dozens of authorized customers pay for the use of VirtualApp commercial code, and the number of APPs that integrate VirtualApp code starts more than 200 million times a day. Thousands of Android engineers provide us with user feedback in different scenarios, and VirtualApp commercial version code has become increasingly sophisticated through the continuous efforts of our technical team to optimize. After you get the authorization, you will become one of them and enjoy the fruits of continuous iteration and improvement. And we can cooperate with our authorized customers in operation, technology and business. -Person in charge: General Zhang
-Mobile: +86 1303217777 7
-Wechat: 10890
+Person in charge: General Chen
+Mobile: +86 1303217777 7(wechat id)
Company email: zl@aluohe.com From acd785d22e457e82e75331b22a739a32b4cdf785 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 16 Jan 2020 10:46:50 +0800 Subject: [PATCH 160/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11a3fb451..b61eaf332 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Luohe Technology has set up companies in Shanghai, Shenzhen and Shandong. From 2 Person in charge: General Chen
Mobile: +86 1303217777 7(wechat id)
-Company email: zl@aluohe.com +Company email: FF@aluohe.com Strictness Disclaimer From 8f599ee380b97195d5f8ee65408efecd134836bb Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 28 Jan 2020 21:51:22 +0800 Subject: [PATCH 161/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b61eaf332..ed069a4a3 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Luohe Technology has set up companies in Shanghai, Shenzhen and Shandong. From 2 Person in charge: General Chen
-Mobile: +86 1303217777 7(wechat id)
+Mobile: +86 16502177777(wechat id)
Company email: FF@aluohe.com From 02cb836801fe051d37ae462e53c93eb082d192a9 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Fri, 6 Mar 2020 13:10:06 +0800 Subject: [PATCH 162/334] Update CHINESE.md --- CHINESE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 8ee95a4f7..2e20e0503 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -120,6 +120,15 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 1月16号 至 2020年 3月6号 商业版代码更新内容** + +250、调整 lib 重定向逻辑
+249、修复三星 10.0 系统上的崩溃问题
+248、修复 release build 的 hook 异常
+247、增加 SandHook 的 proguard 规则
+246、修复对部分 App 中 VirtualApk 的兼容问题
+245、修复 VA 内部请求安装 apk 失败的问题
+ **2019年 12月26号 至 2020年 1月15号 商业版代码更新内容** 244、修复 Android Q 遗漏的 hook
From e9f4260171a35dbe750bf025d5e8df376684ee6f Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Mon, 23 Mar 2020 13:58:46 +0800 Subject: [PATCH 163/334] Update CHINESE.md --- CHINESE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 2e20e0503..a219911c9 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -120,6 +120,15 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 3月7号 至 2020年 3月23号 商业版代码更新内容** + +256、修复微信同时打开两个页面问题
+255、修复微信登陆成功但是返回登陆页面的问题
+254、修复最新版 QQ 无法下载附件的问题
+253、更新 SandHook 版本
+252、修复 9.0 以上安装未签名Apk问题
+251、修复 10.0 的定位问题
+ **2020年 1月16号 至 2020年 3月6号 商业版代码更新内容** 250、调整 lib 重定向逻辑
From f69a1021399e12c046c3f63fa213ce6ec1968e64 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Thu, 23 Apr 2020 13:06:59 +0800 Subject: [PATCH 164/334] Update CHINESE.md --- CHINESE.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index a219911c9..706a53b70 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -120,6 +120,15 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 3月24号 至 2020年 4月23号 商业版代码更新内容** + +262、修复 Vivo 设备提示安装游戏 SDK 的问题
+261、修复 Android Q 无法加载部分系统 so 的问题
+260、修复华为设备微博未响应
+259、忽略不必要的权限检查造成的崩溃
+258、修复 WPS 分享文件崩溃的问题
+257、部分 10.0 设备的闪退问题
+ **2020年 3月7号 至 2020年 3月23号 商业版代码更新内容** 256、修复微信同时打开两个页面问题
From 39190233ae5eb5b077e1911d811875045717cfbe Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Mon, 18 May 2020 11:36:00 +0800 Subject: [PATCH 165/334] Update CHINESE.md --- CHINESE.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 706a53b70..c22e23dc0 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -120,6 +120,14 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 + +**2020年 4月24号 至 2020年 5月18号 商业版代码更新内容** + +266、修复 sh 调用错误
+265、修复 9.0 以上最新版 Facebook 无法登陆的问题
+264、帮助企业微信修复启动虚拟存储的情况下无法拍照的问题
+263、修复某些情况下 64位 app 打不开 Activity 的问题
+ **2020年 3月24号 至 2020年 4月23号 商业版代码更新内容** 262、修复 Vivo 设备提示安装游戏 SDK 的问题
From ff9090a1c3bc84440185aaa828a3ef5d9326a97c Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 2 Jun 2020 16:05:13 +0800 Subject: [PATCH 166/334] Update CHINESE.md --- CHINESE.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index c22e23dc0..4907ba8ce 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -108,8 +108,9 @@ VA实例
-商务负责人:陈总
-电话:165-021-77777(微信同号)
+负责人:张总
+手机:130-321-77777
+QQ/微信:10890

From e4493baebe41b0c7922a07fce860f210e1db06c4 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Tue, 2 Jun 2020 16:07:38 +0800 Subject: [PATCH 167/334] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ed069a4a3..076de4143 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,10 @@ Authorization Note Luohe Technology has set up companies in Shanghai, Shenzhen and Shandong. From 2015 to 2018, it applied for many VirtualApp intellectual property rights, which are protected by the Intellectual Property Law of the People's Republic of China. When you need to use the VirtualApp code on Github, please purchase the commercial license. After obtaining the commercial license, you will receive the full source code of the commercial version of VirtualApp provided by us. Dozens of authorized customers pay for the use of VirtualApp commercial code, and the number of APPs that integrate VirtualApp code starts more than 200 million times a day. Thousands of Android engineers provide us with user feedback in different scenarios, and VirtualApp commercial version code has become increasingly sophisticated through the continuous efforts of our technical team to optimize. After you get the authorization, you will become one of them and enjoy the fruits of continuous iteration and improvement. And we can cooperate with our authorized customers in operation, technology and business. -Person in charge: General Chen
-Mobile: +86 16502177777(wechat id)
-Company email: FF@aluohe.com +Person in charge: General Zhang
+Mobile: +86 1303217777 7
+Wechat: 10890
+Company email: zl@aluohe.com Strictness Disclaimer From eac773810bece21012fd9dc890010b30f2e0c063 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Wed, 8 Jul 2020 12:39:46 +0800 Subject: [PATCH 168/334] Update CHINESE.md --- CHINESE.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 4907ba8ce..4eb8cfbda 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,11 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 5月19号 至 2020年 7月9号 商业版代码更新内容** + +269、初步适配 Android 11 beta1
+268、修复小红书多开闪退的问题
+267、修复某些 App 多开报“应用签名被篡改”的问题
**2020年 4月24号 至 2020年 5月18号 商业版代码更新内容** From 157954560f590da00263f8b625508d7eda5f57c0 Mon Sep 17 00:00:00 2001 From: ganyao114 <939543405@qq.com> Date: Sun, 23 Aug 2020 00:05:24 +0800 Subject: [PATCH 169/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 4eb8cfbda..9f650d221 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,12 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 7月10号 至 2020年 8月22号 商业版代码更新内容** + +272、修复 Service 创建
+271、添加 NotificationService 缺失的 Hook
+270、修复 Yotube 崩溃
+ **2020年 5月19号 至 2020年 7月9号 商业版代码更新内容** 269、初步适配 Android 11 beta1
From f0ef26691d2219be5b8438dc0007654c47565f5f Mon Sep 17 00:00:00 2001 From: ganyao114 <18422727+ganyao114@users.noreply.github.com> Date: Sat, 12 Sep 2020 18:18:37 +0800 Subject: [PATCH 170/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 9f650d221..fbf81b5b6 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,12 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 8月23号 至 2020年 9月212号 商业版代码更新内容** + +275、添加缺失的 service hook
+274、修复百度翻译无法启动的问题
+273、修复 GP 下载的 split app 无法启动的问题
+ **2020年 7月10号 至 2020年 8月22号 商业版代码更新内容** 272、修复 Service 创建
From 37e67ac6b92d7edef5f36d4671d9a0c92cb6ee02 Mon Sep 17 00:00:00 2001 From: ganyao114 <18422727+ganyao114@users.noreply.github.com> Date: Thu, 17 Sep 2020 10:40:31 +0800 Subject: [PATCH 171/334] Update CHINESE.md --- CHINESE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index fbf81b5b6..960475b8e 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -110,7 +110,7 @@ VA实例
负责人:张总
手机:130-321-77777
-QQ/微信:10890
+微信:10890

@@ -121,7 +121,7 @@ QQ/微信:10890
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 8月23号 至 2020年 9月212号 商业版代码更新内容** +**2020年 8月23号 至 2020年 9月12号 商业版代码更新内容** 275、添加缺失的 service hook
274、修复百度翻译无法启动的问题
From a3e6594880a7ee1630d18c4d9234530d6fedc102 Mon Sep 17 00:00:00 2001 From: ganyao114 <18422727+ganyao114@users.noreply.github.com> Date: Thu, 15 Oct 2020 12:47:59 +0800 Subject: [PATCH 172/334] Update CHINESE.md --- CHINESE.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index 960475b8e..f4e02c924 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,12 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 9月13号 至 2020年 10月15号 商业版代码更新内容** + +278、修复 64 位 App 无法调用 32 位 App 的问题
+277、修复 Android R 加载 HttpClient 的问题
+276、修复 Android R debug 模式下的崩溃问题
+ **2020年 8月23号 至 2020年 9月12号 商业版代码更新内容** 275、添加缺失的 service hook
From 745579f7b56545c58bf0dd3e91baf38faf7432b6 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 28 Oct 2020 14:43:14 +0800 Subject: [PATCH 173/334] Update CHINESE.md --- CHINESE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHINESE.md b/CHINESE.md index f4e02c924..cdc2eefb4 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,6 +121,17 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2020年 10月15号 至 2020年 10月28号 商业版代码更新内容** +286、添加系统Package缓存,优化性能 +285、修复disabled组件还能被PMS查询的BUG +284、修复微信部分界面Launch行为异常的问题 +283、修复ContentProvider.getCallingPackage返回Host包名的BUG +282、修复uid虚拟化的BUG,解决部分app权限检查失败的问题 +281、重写PendingIntent, IntentSender的实现 +280、优化进程管理,修复长期存在的概率性进程死锁问题 +279、重写Service实现,Service生命周期更准确,不容易被杀死 + + **2020年 9月13号 至 2020年 10月15号 商业版代码更新内容** 278、修复 64 位 App 无法调用 32 位 App 的问题
From b994710039341666d1c35f2c26ceff4681ef4b6e Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 28 Oct 2020 14:43:51 +0800 Subject: [PATCH 174/334] Update CHINESE.md --- CHINESE.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index cdc2eefb4..28e37cabe 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -122,14 +122,15 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 **2020年 10月15号 至 2020年 10月28号 商业版代码更新内容** -286、添加系统Package缓存,优化性能 -285、修复disabled组件还能被PMS查询的BUG -284、修复微信部分界面Launch行为异常的问题 -283、修复ContentProvider.getCallingPackage返回Host包名的BUG -282、修复uid虚拟化的BUG,解决部分app权限检查失败的问题 -281、重写PendingIntent, IntentSender的实现 -280、优化进程管理,修复长期存在的概率性进程死锁问题 -279、重写Service实现,Service生命周期更准确,不容易被杀死 + +286、添加系统Package缓存,优化性能
+285、修复disabled组件还能被PMS查询的BUG
+284、修复微信部分界面Launch行为异常的问题
+283、修复ContentProvider.getCallingPackage返回Host包名的BUG
+282、修复uid虚拟化的BUG,解决部分app权限检查失败的问题
+281、重写PendingIntent, IntentSender的实现
+280、优化进程管理,修复长期存在的概率性进程死锁问题
+279、重写Service实现,Service生命周期更准确,不容易被杀死
**2020年 9月13号 至 2020年 10月15号 商业版代码更新内容** From 23248d0cb009be340522fec1eb011516f5262684 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 28 Oct 2020 14:45:31 +0800 Subject: [PATCH 175/334] Update CHINESE.md --- CHINESE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 28e37cabe..21f42fcbf 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -89,16 +89,16 @@ VA实例 **Github上代码**已在2017年12月份**停止更新**,商业版代码在持续更新中,并有以下提升: -1. 兼容最新Android Q +1. 兼容最新Android R 2. 不易被杀毒软件误报 3. 框架优化,性能大幅提升 4. 手机系统及APP兼容性大幅提升 5. 完美运行Google服务 6. 支持运行纯64位App -7. 支持Dalvik和Art的Java Hook(API同Xposed) +7. 内置`XPosed Hook`框架 8. 增加定位模拟代码 9. 增加改机代码 -10. 其他180多项问题的修复和改进,详情请见下表 +10. 其他近300项问题的修复和改进,详情请见下表 授权说明 From dfbcd03171ea9b1e8e0fa7ed171bff59e60cb720 Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 28 Oct 2020 14:46:55 +0800 Subject: [PATCH 176/334] Update CHINESE.md --- CHINESE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index 21f42fcbf..a72a4ffbe 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -41,7 +41,7 @@ VA的其他特性 进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 - 全版本支持
-支持4.1-10.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 +支持4.1-11.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 - 易扩展与集成
VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 From e66963d0b2a0b9d0eb311ac51b434f9e2a78dcac Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 13 Nov 2020 15:41:16 +0800 Subject: [PATCH 177/334] Update CHINESE.md --- CHINESE.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index a72a4ffbe..685ac9326 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,8 +121,15 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 10月15号 至 2020年 10月28号 商业版代码更新内容** - +**2020年 10月15号 至 2020年 11月13号 商业版代码更新内容** + +293、支持安装Splits APK
+292、支持动态配置主包环境
+291、修复32位QQ调用64位微信卡顿的问题
+290、修复Messenger调用Facebook崩溃的问题
+289、优化对Google服务框架的支持
+288、实现新的扩展包同步机制
+287、修复Android 11正式版的异常问题
286、添加系统Package缓存,优化性能
285、修复disabled组件还能被PMS查询的BUG
284、修复微信部分界面Launch行为异常的问题
From 6d48567a9a65c0d7868dea78f041ea459832d184 Mon Sep 17 00:00:00 2001 From: Lody Date: Sat, 14 Nov 2020 22:24:33 +0800 Subject: [PATCH 178/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 685ac9326..b97d875ca 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -123,6 +123,7 @@ VA实例 **2020年 10月15号 至 2020年 11月13号 商业版代码更新内容** +294、修复LOL手游的登录异常问题
293、支持安装Splits APK
292、支持动态配置主包环境
291、修复32位QQ调用64位微信卡顿的问题
From 01c1abd027dc94c395cfaae2d417c06c9bc6ea65 Mon Sep 17 00:00:00 2001 From: Lody Date: Sat, 14 Nov 2020 22:26:40 +0800 Subject: [PATCH 179/334] Update CHINESE.md --- CHINESE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHINESE.md b/CHINESE.md index b97d875ca..1a4de13fe 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,8 +121,9 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 10月15号 至 2020年 11月13号 商业版代码更新内容** +**2020年 10月15号 至 2020年 11月14号 商业版代码更新内容** +295、修复VApp卸载重装的BUG
294、修复LOL手游的登录异常问题
293、支持安装Splits APK
292、支持动态配置主包环境
From 94cad62ca6bb501a35b830fd2e6b6e117c2758f5 Mon Sep 17 00:00:00 2001 From: Lody Date: Mon, 16 Nov 2020 12:25:46 +0800 Subject: [PATCH 180/334] Update CHINESE.md --- CHINESE.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index 1a4de13fe..2a1907389 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,8 +121,10 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 10月15号 至 2020年 11月14号 商业版代码更新内容** - +**2020年 10月15号 至 2020年 11月16号 商业版代码更新内容** +298、重构VApp安装框架
+297、重构virtual文件系统
+296、修复某些情况下WebView无法启动的问题
295、修复VApp卸载重装的BUG
294、修复LOL手游的登录异常问题
293、支持安装Splits APK
From 1005f34255f416609828738c91fd93a8135314e0 Mon Sep 17 00:00:00 2001 From: Lody Date: Mon, 16 Nov 2020 12:26:09 +0800 Subject: [PATCH 181/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 2a1907389..c025daacb 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -122,6 +122,7 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 **2020年 10月15号 至 2020年 11月16号 商业版代码更新内容** + 298、重构VApp安装框架
297、重构virtual文件系统
296、修复某些情况下WebView无法启动的问题
From 8c19ddf468144efaf2e3369486d7098f50a2bcba Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 13 Dec 2020 17:10:44 +0800 Subject: [PATCH 182/334] Update CHINESE.md --- CHINESE.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHINESE.md b/CHINESE.md index c025daacb..1e666a237 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -121,8 +121,11 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 10月15号 至 2020年 11月16号 商业版代码更新内容** - +**2020年 10月15号 至 2020年 12月13号 商业版代码更新内容** +302、修复某些情况系统任务栈只显示最后一个的问题
+301、完善不同平台的构建脚本
+300、修复Android 11无法读取obb的问题
+299、解决软件无法向后兼容的问题
298、重构VApp安装框架
297、重构virtual文件系统
296、修复某些情况下WebView无法启动的问题
From daac7e6d38144381f15de6dabd410354efbc17a9 Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 13 Dec 2020 17:14:51 +0800 Subject: [PATCH 183/334] Update CHINESE.md --- CHINESE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHINESE.md b/CHINESE.md index 1e666a237..cbe67995b 100644 --- a/CHINESE.md +++ b/CHINESE.md @@ -122,6 +122,7 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 **2020年 10月15号 至 2020年 12月13号 商业版代码更新内容** + 302、修复某些情况系统任务栈只显示最后一个的问题
301、完善不同平台的构建脚本
300、修复Android 11无法读取obb的问题
From c79fe53fff3799ea25e0a150f47acb5c33eae8fc Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 13 Dec 2020 17:17:19 +0800 Subject: [PATCH 184/334] Delete README.md --- README.md | 254 ------------------------------------------------------ 1 file changed, 254 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 076de4143..000000000 --- a/README.md +++ /dev/null @@ -1,254 +0,0 @@ -[![VA banner](https://raw.githubusercontent.com/asLody/VirtualApp/master/Logo.png)](https://github.com/asLody/VirtualApp) - -[中文版](CHINESE.md "中文") - -Project Profile ---------------- - -VirtualApp is a commercial project developed and operated by Luohe technology, which creates a virtual space within your App. You can `install, start and uninstall APK arbitrarily in the virtual space`, which is isolated from the outside, like a *sandbox*. -APK running in VA does not need to be `installed externally`, that is, the VA supports running APK without installation. -VA is currently widely used in plug-in development, non-thermal update, cloud control automation, multi-open, mobile game rent number, mobile game handle activation free, block chain, mobile office security, military and government secrecy, mobile phone simulation information, script automation, automated testing and other technical fields, but it is not limited to this. Android itself is an extremely open platform, `and the ability to run APK without installing it opens up unlimited possibilities -- which depend on your imagination.` -The code on Github has been updated since December 2017. The commercial version of the code is still being updated, with the following improvements: - -1. New Code Characteristics -2. Framework optimization and performance improvement -3. Compatibility of mobile phone system and APP has been greatly improved -4. Run Google services perfectly -5. Compatibility with the latest Android Q (10.0) -6. Support running 64-bit App -7. Java Hook that supports Dalvik and Art (API and Xposed) -8. Add positioning simulation code -9. Add the machine changing code -10. Please refer to the table below for details of the repair and improvement of more than 180 other problems - - -Authorization Note ------------------- - -Luohe Technology has set up companies in Shanghai, Shenzhen and Shandong. From 2015 to 2018, it applied for many VirtualApp intellectual property rights, which are protected by the Intellectual Property Law of the People's Republic of China. When you need to use the VirtualApp code on Github, please purchase the commercial license. After obtaining the commercial license, you will receive the full source code of the commercial version of VirtualApp provided by us. Dozens of authorized customers pay for the use of VirtualApp commercial code, and the number of APPs that integrate VirtualApp code starts more than 200 million times a day. Thousands of Android engineers provide us with user feedback in different scenarios, and VirtualApp commercial version code has become increasingly sophisticated through the continuous efforts of our technical team to optimize. After you get the authorization, you will become one of them and enjoy the fruits of continuous iteration and improvement. And we can cooperate with our authorized customers in operation, technology and business. - - -Person in charge: General Zhang
-Mobile: +86 1303217777 7
-Wechat: 10890
-Company email: zl@aluohe.com - - -Strictness Disclaimer ---------------------- - -If you use VirtualApp for internal use, commercial profit or upload to the application market without authorization, we will directly collect evidence and report to the police (copyright infringement) or prosecute, which will cause criminal liability and legal proceedings to your company and affect your company's goodwill and investment. Buying a commercial license saves you a lot of development, testing, and refining time, allowing you more time to innovate and monetize. - - - -**The updating contents of commercial version code from December 13, 2018 to June 13, 2019** - -206. Preliminary support for pure 64-bit mode to meet the requirements of the Google Market
-205. Preliminary support for Android Q beta4
-204. Fix install of Huolala
-203. Fix check logic for 64bit apk
-202. Support NetworkSecurityConfig
-201. Rewrite Component State Manager
-200. Optimaize compatibility of MIUI/EMUI ContentProvider
-199. Fix StorageStats Hook
-198. Fix login of Kuaishou
-197. Fix support for some plugin frameworks(Small, Atlas)
-196. Fix login of Facebook
-195. Fix so load error of some app download from Google Play(COC)
-194. Fix suppport for split apk
-193. Fix crash of Youtube
-192. Fix crash of Youku
-191. Fix conflict of broadcast namespace
-190. Add a new policy to bypass Hidden Policy API above Android P
-189. Pre support for Android Q(beta1)
-188. Fix access to SD Card in some huawei devices
-187. Fix some launch process failure
-186. Fix get native symbol failure in some 4.4 devices
-185. Fix got package name failure by WebView in some devices
-184. Fix detail of service
-183. Optimize launch speed
- -The updating contents of commercial version code from January 1, 2018 to December 13, 2018. - -182. Fix WebView loading failure in a few models
-181. Fix Lib decision problems
-180. Fix the problem that some Huawei models could not read memory CARDS
-179. Fix possible problems with the Service
-178. Allow judging whether an Activity is started externally based on intent
-177. Fix incorrect environment boot of Gms and Google Play on some models
-176. Fix compatibility problems caused by the StaticBroadcast new implementation
-175. Fix the problem that apache. HTTP. Legacy cannot be used on Android P
-174. Implement Native trace
-173. Optimize IO Redirect performance
-172. Fix the occasional network failure of wechat
-171. Fix bugs with incorrect small probability process attach
-170. ROADMAP for the next stage
-169. Solve the problem caused by Android P's inability to register more than 1000 broadcasts
-168. Fix DeadLock that may cause ANR
-167. Fix the problem of partial app dynamic loading failure
-166. Fix the problem that black screen appears when some models are opened for the first time under the operating environment without installation
-165. Compatible with many mainstream Android emulators
-164. Optimize start-up performance
-163. Resolve multiple memory leaks
-162. Fix IO Redirect priority issues
-161. Fix the problem of no network connection for Messenger device below 8.0
-160. Fix Bug that remained in the internal app when the external app was uninstalled in dual-open mode
-159. Fix the problem of some tencent reinforcement can not run
-158. Fix the BUG that Instagram could not log into Facebook
-157. Fix Bug that may be started repeatedly with low probability
-156. Fix Bug of the GET_PERMISSIONS without authorization
-155. Fix Bug of starting Activity Intent Sender
-154. Fix the problem that activity on some vivo devices could not be started
-153. Fix the problem that the app could not call the external app to select the file
-152. Improve the compatibility of Android P
-151. Google service compatible with Android P
-150. Solve some abnormal functions of Messenger
-149. Improve IO Redirect
-148. A large number of Gms are adapted to fix the problem of unlimited process restart during Gms operation
-147. Re-implement the operation mechanism of Service
-146. Improve 64 bit and provide API for some ROM configuration 64bit Engine permissions
-145. Fix Activity startup problem on 4.4 device
-144. Support the exclude From Recent attribute
-143. Fix the problem that Instagram could not log into Facebook
-142. Fix the problem of Facebook's first login flashback
-141. Support to run Gms, Google play and play game in 64-bit mode
-140. Support downloading and installing apps in Google Play with dual-open/install-free running
-139. Fix Bug of Download Manager
-138. Fix the BUG of restarting the interface when Google play returned to the upper layer
-137. Fix the so decision-making problem in the installation-free mode
-136. Optimize the build script to facilitate the introduction of projects
-135. Fix the problem that the mobile MM SDK could not be started
-134. Fix the BUG of WeChat shake
-133. Fix the unstable BUG of ZTE equipment
-132. Support ARM64 IO Redirect
-131. Fix the BUG that no updates are made to the internal app when the external app is updated in USE_OUTSIDE mode
-130. Compatible with the latest version of Android 9.0(code-named pie) and the four Preview versions released before the official version
-129. Compatible with x86 devices with built-in Houdini
-128. Windows preview technology enables App to start at the same speed as real App
-127. New Activity Stack to improve running quality of APP
-126. Solve the abnormal operation of App connected to Atlas Framework
-125. Be able to define the specific behavior of the virtual app returning to the desktop
-124. Now the app is dynamically updated with the system in double-open mode, without manual check
-123. When target Sdk Version >= 26, the lower version of the app can still run normally
-122. QDroid virtual engine (beta) compatible with tencent game manager
-121. Refactor a lot of underlying code to greatly improve the running speed
-120. Fix the problem that netease news cannot be cancelled after sharing on weibo
-119. Fix the problem that App custom permissions cannot be recognized
-118. Fix the problem that the app could not be started due to ink stains
-117. Fix the problem that some government apps could not be started
-116. See the code for changes to the API
-115. Fixed the mutual call problem of Samsung series of applications
-114. Fix the account problems of Xiaomi applications in non-xiaomi systems
-113. Repair third-party calls such as share/send, and the returned page is abnormal
-112. Fix the problem that App prompt cannot be installed
-111. Use the third-party App and encrypt the uri
-110. Adapt to the bangs
-109. Adapt to the hook of Xiaomi ROM
-108. Adapt to the problem of Nubian recording
-107. Permission control of internal suspension window
-106. Optimize the processing of customized notification bar
-105. Fix the INCLUDE_CODE permission problem of Context
-104. Adapt to corner marks of Huawei and Oppo
-103. Fix the problem of Baidu video process restart
-102. Fix some snap chat start-up problems
-101. Adapt to autofill service, such as piexl series
-100. Improve 64-bit IO hook
-99. Optimize hook library compatibility, add back dlopen
-98. The so of the 64-bit extension package is moved to the 32-bit master package. (after jni code changes, please build it once before running)
-Notification Bar Change: Adapt 8.1 Notification Channel; Remove all notifications of the application when the application is removed
-96. Compatible with some Apps, need to set android:largeHeap=true
-95. Fix the problem of ffmpeg library video can not play
-94. Optimize horizontal and vertical screen switching
-93. Reduce the limit of calling external activities with intent.action_view.
-92. Compatible with MG SDK
-91. 64-bit support is still in development
-90. Update the confusion configuration app/proguard-rules.pro, must add the rule -dontshrink
-89. Optimize the simulation model, for example: after simulation, device verification does not appear in some Apps
-88. Improve dex2oat compatibility
-87. Optimize simulation positioning
-86. Remove dlopen
-85. TargetVersion can be changed to 26: support dynamic permission application for app with targetVersion < 23 and file Uri with targetVersion < 24
-84. Install Package changed to the default asynchronous form
-83. Support 64-bit mode and switch back to aidl
-82. Remove Setting Handler can now dynamically set special rules, which are stored and do not need to be set repeatedly
-81. Add 2 native_setup
-80. Improve jobService compatibility
-79. Shortcut Service: Associate VASettings.ENABLE_INNER_SHORTCUT
-78. For the sake of stability and operational efficiency, remove the previous version of bluetooth and wifi, and do not declare the adaption of permissions.
-77. Increase the broadcast Constants of app startup exceptions with ACTION_PROCESS_ERROR
-76. Fix a few game screen judgment problems
-75. Demo adds model simulation
-74. Vivo ADAPTS a custom permission (background popover). VA is to return a historical activity to the foreground, which vivo needs.
-73. If there is no bluetooth permission, return the default value (for overseas use)
-72. Fix the uid permission check problem
-71. Security update and file permission control for internal applications
-70. Improve the compatibility of internal app calls, third-party login and sharing
-69. Automatically filter unauthorized external contentproviders
-68. Added function: check the permission of internal app (closed by default)
-67. Model simulation: Build class and build.prop
-66. Improve app compatibility for legu reinforcement
-65. Adapt to Samsung wifimanager
-64. Fix a parameter passing problem in ipc framework (IPCMethod class must be updated)
-63. Complete the hook of 7.0 notice bar
-62. Fix hook of 8.0 dynamic shortcut menu
-61. Setting Handler adds an adaptor interface, mainly suitable for various games
-60. Function changes: Google automatic installation to manual installation, to avoid the first time to start too long
-59. Access to an external Content Provider can be prohibited
-58. Adapt to the number of Huawei desktop icons
-57. Permission classification annotation, indicating that permission can be deleted
-56. Add dual-open mode App to follow the external upgrade switch
-55. Improve jni compatibility of app
-54. Improve compatibility with other plug-in frameworks for app integration
-53. Add setting interface and set according to the package name
-52. Increase the Uri adaptation range to support sharing and viewing files through uris
-51. Fix a problem with Samsung 8.0
-50. Improve the compatibility of app components with the system, better compatible with chrome webview and Google service.
-49. Improve the stability of ART
-48. Increase the scope of camera adaptation
-47. Support shortcut management of internal App under 8.0
-46. Fix exec exceptions
-45. Improve stability (Fix WeChat login backout)
-44. Solve the problem of WeChat database crash
-43. Fixed part 4.4 equipment crash
-42. Fix the problems that the background application is easy to be killed, tudou video black screen, sina weibo cannot be opened, and youku cannot exit after two returns.
-41. Add the survival mechanism of the application, and double-open APP is more difficult to be killed.
-40. Optimize start-up performance of virtual engine.
-39. Compatible with most of the reinforcement and the compatibility of third-party APP increased by 40% compared with the previous version.
-38. Fixed some ROMs with incorrect shortcut icons
-37. Compatibility with previous component Stub File Provider
-36. Virtual IMEI for adapting part of the new ROM
-35. Improve process initialization code and increase stability
-34. Add internal transmission Intent.ACTION_BOOT_COMPLETED broadcast and the switch can be set
-33. Adapt to the Google play game, and support the game to log in with Google
-32. Compatible with Google service framework of android O
-31. Compatible with android O shortcuts
-30. Adapt to headset mode
-29. Some ROMs limit the size of intent. Demo adds zoom shortcut icon code
-28. Fix the Bug in the case of multiple openings
-27. Fix the Bug in Media Controller in some cases
-26. Fix Stub File Provider error of 4.1.2
-25. Share uri processing
-24. Fix the callback of cross-app call Activity
-23. Notification bar blocking switch of foreground service
-22. Attached doc
-21. Improve the CHOOSE callback of intent within VA
-20. The notification bar of Android O is compatible with 2
-19. Optimize ipc framework to improve the survival accuracy of binder
-18. JNI log switch Android.mk: LOCAL_CFLAGS+=-DLOG_ENABLE
-17. Confusion Configuration
-16. Android O Notice Bar Adaptation
-15. Fix problems with some app network CARDS
-14. Dl_open (jni load) compatible with android 8.0
-13. Fix the Bug of Huawei emui8.0
-12. Improve positioning
-11. Set up mobile phone information and imei camouflage algorithm
-10. Adapt to a certain function of 8.0(main app: whats App)
-9. Fix the problem that internal WeChat and other applications could not update pictures and video
-8. Demo adds installation monitoring and automatically updates the application of clone mode
-7. 7.0 File Provider Adaptation
-6. Add location code
-5. Architectural optimization of code
-4. Different features from the open source version
-3. Solve some problems of WeChat sealing
-2. Fix compatibility of some models
-1. Fix 12 minor bugs From f0522b80612c2991897988e5347a65b49983163d Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 13 Dec 2020 17:17:40 +0800 Subject: [PATCH 185/334] Rename CHINESE.md to README.md --- CHINESE.md => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CHINESE.md => README.md (100%) diff --git a/CHINESE.md b/README.md similarity index 100% rename from CHINESE.md rename to README.md From 31ed5287f949a8a43a19aba3a0431f5008b67f4f Mon Sep 17 00:00:00 2001 From: Lody Date: Thu, 24 Dec 2020 02:10:53 +0800 Subject: [PATCH 186/334] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cbe67995b..7705afab2 100644 --- a/README.md +++ b/README.md @@ -121,8 +121,13 @@ VA实例 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 10月15号 至 2020年 12月13号 商业版代码更新内容** +**2020年 10月15号 至 2020年 12月24号 商业版代码更新内容** +307、支持Hook @CriticalNative Method
+306、修复JDK 13无法编译运行的问题
+305、修复Service部分情况可能crash的问题
+304、修复Android 11无法加载外部存储私有数据的问题
+303、修复低版本app无法使用org.apache.http.legacy的问题
302、修复某些情况系统任务栈只显示最后一个的问题
301、完善不同平台的构建脚本
300、修复Android 11无法读取obb的问题
From 46db0a8807e116a2111b669994b953fbb1fe72ed Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 15 Jan 2021 21:02:21 +0800 Subject: [PATCH 187/334] Update README.md --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7705afab2..fb2a41980 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,7 @@ VA实例 授权说明 ------ - -罗盒科技在上海及山东济宁设有公司,于2015年至2018年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的VirtualApp代码时,**请购买商业授权**,获取商业授权后将可以收到我们提供的VirtualApp商业版全部源代码。数十家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,数千位安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队的不断努力优化,VirtualApp商业版代码已经日益完善。`您获取授权后,将成为其中一员,享受这些不断迭代完善后的成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` - +VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,于2015年至2021年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当年的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
负责人:张总
@@ -116,8 +114,7 @@ VA实例 严重声明 ------ - -您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们发现后将直接取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善时间,让您有更多时间用于创新及盈利`。
+您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们将取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善兼容性的时间,让您更多时间用于创新及盈利。`罗盒科技已在2020年报警和起诉了一些个人及公司。
2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 From bce1886edd6038ff259b90328ec28fdc7d7d9489 Mon Sep 17 00:00:00 2001 From: Lody Date: Sun, 17 Jan 2021 02:46:04 +0800 Subject: [PATCH 188/334] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fb2a41980..9e7fed6fa 100644 --- a/README.md +++ b/README.md @@ -118,8 +118,13 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 10月15号 至 2020年 12月24号 商业版代码更新内容** +**2020年 10月15号 至 2021年 1月17号 商业版代码更新内容** +312、解决ext插件部分情况下卡死的问题
+311、支持Google Play在容器中下载APP
+310、修复Android 11 QQ无法显示图片的问题
+309、兼容Android 11运行Google Service
+308、解决Android 11无法运行chromium
307、支持Hook @CriticalNative Method
306、修复JDK 13无法编译运行的问题
305、修复Service部分情况可能crash的问题
From a6516e032defcfe42697ad5ca5a1205a28f0de74 Mon Sep 17 00:00:00 2001 From: Lody Date: Mon, 15 Feb 2021 12:19:58 +0800 Subject: [PATCH 189/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e7fed6fa..dc617c58c 100644 --- a/README.md +++ b/README.md @@ -107,8 +107,8 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
负责人:张总
-手机:130-321-77777
-微信:10890
+手机:165-021-77777
+微信:LuoHeKeJi

From 62b0878dd9a38de53177a1d431cf901f3e2644b6 Mon Sep 17 00:00:00 2001 From: Lody Date: Tue, 23 Feb 2021 15:44:16 +0800 Subject: [PATCH 190/334] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dc617c58c..f0cd62f9a 100644 --- a/README.md +++ b/README.md @@ -118,8 +118,12 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2020年 10月15号 至 2021年 1月17号 商业版代码更新内容** +**2020年 10月15号 至 2021年 2月23号 商业版代码更新内容** +316、解决新版爱加密、邦邦等加固的兼容性
+315、修复WhatsApp不显示冷启动Splash的问题
+314、优化对系统app的识别
+313、完善多用户环境下的支持
312、解决ext插件部分情况下卡死的问题
311、支持Google Play在容器中下载APP
310、修复Android 11 QQ无法显示图片的问题
From bd6f03cfd7cbf3ad63ec6198777a102c18112c2d Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 17 Mar 2021 13:52:25 +0800 Subject: [PATCH 191/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f0cd62f9a..5ef2633d9 100644 --- a/README.md +++ b/README.md @@ -107,8 +107,8 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
负责人:张总
-手机:165-021-77777
-微信:LuoHeKeJi
+手机:130-321-77777
+微信:10890

From 630538463390ae98a3d8dc9acabeea862383612c Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Mon, 29 Mar 2021 22:16:31 +0800 Subject: [PATCH 192/334] Update README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 5ef2633d9..6bad16a92 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,15 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2021年 2月24号 至 2021年 3月29号 商业版代码更新内容** + +322、支持VAPP设置电源优化
+321、修复缺失权限声明
+320、修复Android 11上android.test.base库的引用
+319、优化ext插件判断
+318、优化安装时ABI的选择
+317、修复Google文档在Android 11上崩溃的问题
+ **2020年 10月15号 至 2021年 2月23号 商业版代码更新内容** 316、解决新版爱加密、邦邦等加固的兼容性
From 424fb78c5f0ef7b09b2c0cb26724bda4e7a0c6f7 Mon Sep 17 00:00:00 2001 From: Lody Date: Sat, 24 Apr 2021 13:30:43 +0800 Subject: [PATCH 193/334] Update README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6bad16a92..5b0ab487c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 项目简介 --- -VirtualApp(以下简称:VA)是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。其产品形态为高可扩展,可定制的集成SDK,您可以基于VA或者使用VA定制开发各种看似不可能完成的项目。VA目前被广泛应用于插件化开发、无感知热更新、云控自动化、多开、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府保密、手机模拟信息、脚本自动化、自动化测试等技术领域。 +VirtualApp(以下简称:VA)是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。其产品形态为高可扩展,可定制的集成SDK,您可以基于VA或者使用VA定制开发各种看似不可能完成的项目。VA目前被广泛应用于APP多开、手游境外加速、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府数据隔离、手机模拟信息、脚本自动化、插件化开发、无感知热更新、云控等技术领域。 VA的特有能力 --- @@ -89,7 +89,7 @@ VA实例 **Github上代码**已在2017年12月份**停止更新**,商业版代码在持续更新中,并有以下提升: -1. 兼容最新Android R +1. 兼容最新Android S 2. 不易被杀毒软件误报 3. 框架优化,性能大幅提升 4. 手机系统及APP兼容性大幅提升 @@ -118,8 +118,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2021年 2月24号 至 2021年 3月29号 商业版代码更新内容** +**2021年 2月24号 至 2021年 4月24号 商业版代码更新内容** +325、适配多用户环境
+324、修复新版微信的兼容问题
+323、兼容更多企业级加固
322、支持VAPP设置电源优化
321、修复缺失权限声明
320、修复Android 11上android.test.base库的引用
From d29a24f8775a2056c56fe213392efb849c1cac33 Mon Sep 17 00:00:00 2001 From: Lody Date: Thu, 3 Jun 2021 18:53:12 +0800 Subject: [PATCH 194/334] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5b0ab487c..e0032dfc4 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,8 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ 您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们将取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善兼容性的时间,让您更多时间用于创新及盈利。`罗盒科技已在2020年报警和起诉了一些个人及公司。
+**为响应国家对于知识产权的保护号召!凡举报自己所在公司或其他公司未经授权,违法使用VirtualApp代码开发产品的,一经核实给予现金奖励。我们会对举报人身份保密!举报联系微信:10890** + 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 **2021年 2月24号 至 2021年 4月24号 商业版代码更新内容** From 36db476e1287f35c2f4bd46b08ec4e08e8fcc837 Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Thu, 24 Jun 2021 23:13:52 +0800 Subject: [PATCH 195/334] Update README --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index e0032dfc4..2f5690545 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,14 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2021年 4月25号 至 2021年 6月24号 商业版代码更新内容** + +330、修复Android 11 一个权限请求BUG
+329、修复部分cocos2d引擎只显示半屏的问题
+328、修复微信在多用户下不能发送文件的问题
+327、split apk 支持
+326、Android S 支持
+ **2021年 2月24号 至 2021年 4月24号 商业版代码更新内容** 325、适配多用户环境
From 25da52fc8102ea5af6d5bb4a4fa153624556aef1 Mon Sep 17 00:00:00 2001 From: Lody Date: Fri, 9 Jul 2021 02:28:13 +0800 Subject: [PATCH 196/334] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f5690545..dc65a00ef 100644 --- a/README.md +++ b/README.md @@ -120,8 +120,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2021年 4月25号 至 2021年 6月24号 商业版代码更新内容** +**2021年 4月25号 至 2021年 7月9号 商业版代码更新内容** +333、修复Android 12的广播问题
+332、修复微信部分界面状态异常的BUG
+331、修复Outlook、One drive、Teams、Zoom等海外app的支持
330、修复Android 11 一个权限请求BUG
329、修复部分cocos2d引擎只显示半屏的问题
328、修复微信在多用户下不能发送文件的问题
From 45b222cb83aecb6454d6fa9b6f82e00103764126 Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Fri, 6 Aug 2021 11:34:36 +0800 Subject: [PATCH 197/334] Update README --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dc65a00ef..a1dceb552 100644 --- a/README.md +++ b/README.md @@ -120,8 +120,12 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 -**2021年 4月25号 至 2021年 7月9号 商业版代码更新内容** +**2021年 4月25号 至 2021年 8月6号 商业版代码更新内容** +337、修复探探部分手机不能上传头像问题
+336、修复Android 10 华为设备IO重定向问题
+335、调整横竖屏逻辑,减少异常情况发生
+334、添加Activity生命周期的回调接口
333、修复Android 12的广播问题
332、修复微信部分界面状态异常的BUG
331、修复Outlook、One drive、Teams、Zoom等海外app的支持
From ab85a24738d453899d3c416b8526b79d71a64b9e Mon Sep 17 00:00:00 2001 From: Lody Date: Wed, 11 Aug 2021 12:03:35 +0800 Subject: [PATCH 198/334] Update README.md --- README.md | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a1dceb552..9c3c3d026 100644 --- a/README.md +++ b/README.md @@ -49,38 +49,47 @@ VA 的集成方式与普通Android库类似,即使您的App已经完成上线 - 支持Google服务
提供Google服务的支持,以支持海外的App -VA实例 +通过VA可以满足您的不同场景需求,如: --- -- APP多开
-游戏多开,微信多开等 +### 1. 双开/多开需求 ### +VA可以让您在同一部手机上安装多个微信/QQ/WhatsApp/Facebook等APP,实现一部手机,多个账号同时登录。 -- 虚拟手机
-在已有的手机上虚拟出一部专用手机,企业单位可以进行监控管理 +### 2. 移动安全需求 ### +VA是一个标准的沙盒,或者说“虚拟机”,提供了一整套内部与外部的隔离机制,包括但不限于(文件隔离/组件隔离/进程通讯隔离),简单的说VA内部就是一个“完全独立的空间”。
+通过VA可将工作事务与个人事务安全的隔离,互不干扰。稍作定制即可实现应用行为审计、数据加密、数据采集、数据防泄漏、防攻击泄密等移动安全相关的需求。 -- 安全空间
-独立空间,内外隔离,保证内部的私密与安全 +#### 2.1 应用行为审计 #### +通过VA提供的HOOK能力可以实现实时监测用户使用行为,将违规信息上传到服务器;并能轻易实现诸如时间围栏(在某个时间段内能否使用应用的某个功能)、地理围栏(在某个区域内能否使用应用的某个功能)、敏感关键字过滤拦截等功能需求。 -- 游戏租号
-一键上号,一键登陆,免去用户频繁输入账号密码 +#### 2.2 数据加密 #### +通过VA提供的HOOK能力可以实现对应用的全部数据/文件加密,保证数据/文件落地安全。 -- Xposed
-免Root实现Xposed环境 +#### 2.3 数据采集 #### +通过VA提供的HOOK能力可以实现应用数据的实时无感上传需求,如聊天记录、转账记录等,防止事后删除无法追溯。 -- 谷歌空间
-免去国产手机无法使用谷歌服务的烦恼,一键安装使用谷歌应用 +#### 2.4 数据防泄漏 #### +通过VA提供的HOOK能力可以实现应用防复制/粘贴、防截屏/录屏、防分享/转发、水印溯源等需求。 -- 游戏手柄
-免Root方便的使用手柄映射 +#### 2.5 防攻击泄密 #### +通过VA提供的应用管控能力可以将APP获取短信/通讯录/通话记录/后台录音/后台拍照/浏览历史/位置信息等隐私相关的行为完全控制在沙盒中,防止木马/恶意APP获取到用户真实的隐私数据,造成泄密等严重后果。 -- 游戏中心
-免安装运行游戏,多开游戏,游戏内屏录制,统一的游戏更新管理,投射游戏画面到电视。 +### 3. 免ROOT HOOK需求 ### +VA提供了Java与Native的Hook能力,通过VA,您可以轻易实现诸如虚拟定位、改机、APP监控管理、移动安全等各种场景需要的功能。 + +### 4. APP静默安装需求 ### +VA提供了APP静默安装,静默升级,静默卸载的能力。如应用商店或游戏中心在集成VA后可以避免需要用户手动点击确认安装的操作,做到下载后立即安装到VA内,给用户带来“小程序”搬的体验,彻底避免了应用不易被用户安装上的问题。 + +### 5.APP管控需求 ### +通过VA提供的应用管控能力,您可以轻易控制VA中APP的运行界面或运行流程,实现如脚本自动化、特定界面插屏弹窗、修改APP界面内容,修改APP与服务器交互内容等需求。 + +### 6.海外市场需求 ### +VA实现了对Google服务的支持,以支持海外的App运行,比如Twitter、Messenger、WhatsApp、Instagram、FaceBook、Youtube等。 + +### 7.其他需求 ### +VA对于内部的App具有完全的监管和控制能力,几乎能满足您的一切需求! -- 游戏自动化
-方便地模拟用户操作 -- 军政安全
-文件隔离/组件隔离/进程通讯隔离/加密监控等等 From 91459e48d4ac37e3aad450c2276efcbc78ef734a Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Sat, 21 Aug 2021 14:20:39 +0800 Subject: [PATCH 199/334] Update README --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c3c3d026..57ee9e236 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ VA的其他特性 进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 - 全版本支持
-支持4.1-11.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 +支持5.0-12.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 - 易扩展与集成
VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 @@ -129,6 +129,21 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2021年 8月7号 至 2021年 8月21号 商业版代码更新内容** + +349、调整优化gradle脚本
+348、hidedenApiBypass支持Android R+
+347、targetSdk 30 支持
+346、修复VIVO系统服务bug
+345、修复VIVO手机无法使用摄像头的bug
+344、修复dex加载异常状态的获取
+343、修复Android R上libart.so路径问题
+342、修复Andoid Q+ 删除通知的bug
+341、修复APN uri的权限检查
+340、修复Android R暂停恢复线程状态
+339、修复debug模式下部分hook失效情况
+338、修复hook在R之后的一些bug
+ **2021年 4月25号 至 2021年 8月6号 商业版代码更新内容** 337、修复探探部分手机不能上传头像问题
From 1b929486b0b6475efed5493890b2c5ae142f1df3 Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Mon, 20 Sep 2021 00:03:15 +0800 Subject: [PATCH 200/334] Update README --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 57ee9e236..76a3e1fe1 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,22 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2019年3月1日起,我们将VirtualApp商业版代码更新方式升级为`GitHub私有库`方式,授权后即可加入。在授权期内可以和众多授权项目近2100多位安卓工程师一同迭代升级,反馈BUG,我们会第一时间更新解决。 +**2021年 8月22号 至 2021年 9月20号 商业版代码更新内容** + +352、横屏适配
+350、修复部分APP通过file协议安装后无法打开的问题
+350、修复传递给JobIntentService中Intent数据丢失问题
+349、修复JobIntentService第二次调用无法工作的问题
+348、修复华为手机上某些APP奔溃的问题
+347、修复小米手机上游戏登录问题
+346、修复某些应用加固后无法打开的问题
+345、增加对关联启动权限检测
+344、targetSdk 30适配
+343、修复targetSdk为30时,某些应用无法上网的问题
+342、修复targetSdk为30时,sdcard无法访问的问题
+341、编译脚本中使用cmake替换gradle task
+340、移除过时文档
+ **2021年 8月7号 至 2021年 8月21号 商业版代码更新内容** 349、调整优化gradle脚本
From dadc59efc3dab50d15266cf282f09ddc5309ac55 Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Mon, 20 Sep 2021 00:07:26 +0800 Subject: [PATCH 201/334] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76a3e1fe1..8390a7ffd 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, **2021年 8月22号 至 2021年 9月20号 商业版代码更新内容** 352、横屏适配
-350、修复部分APP通过file协议安装后无法打开的问题
+351、修复部分APP通过file协议安装后无法打开的问题
350、修复传递给JobIntentService中Intent数据丢失问题
349、修复JobIntentService第二次调用无法工作的问题
348、修复华为手机上某些APP奔溃的问题
From 5cbf13b13ef07c82f3195099cf9f9c68f57a745f Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Mon, 20 Sep 2021 00:08:33 +0800 Subject: [PATCH 202/334] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8390a7ffd..fd6fac9ab 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, **2021年 8月22号 至 2021年 9月20号 商业版代码更新内容** -352、横屏适配
+352、横屏重新适配
351、修复部分APP通过file协议安装后无法打开的问题
350、修复传递给JobIntentService中Intent数据丢失问题
349、修复JobIntentService第二次调用无法工作的问题
From 688c151efe60f34276bae45ea8ce0bf034e10cf2 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sun, 10 Oct 2021 00:27:30 +0800 Subject: [PATCH 203/334] update readme --- README.md | 754 ++++++++++++++++++++++++++++++++++++---- doc/1.png | Bin 0 -> 19412 bytes doc/2_1.jpg | Bin 0 -> 172000 bytes doc/3_1.png | Bin 0 -> 23584 bytes doc/3_2.png | Bin 0 -> 19042 bytes doc/3_3.png | Bin 0 -> 16103 bytes doc/3_4.png | Bin 0 -> 25288 bytes doc/3_5.png | Bin 0 -> 104820 bytes doc/VADev.md | 538 ++++++++++++++++++++++++++++ doc/va_architecture.jpg | Bin 0 -> 1301947 bytes doc/va_process.jpg | Bin 0 -> 638922 bytes 11 files changed, 1216 insertions(+), 76 deletions(-) create mode 100644 doc/1.png create mode 100644 doc/2_1.jpg create mode 100644 doc/3_1.png create mode 100644 doc/3_2.png create mode 100644 doc/3_3.png create mode 100644 doc/3_4.png create mode 100644 doc/3_5.png create mode 100644 doc/VADev.md create mode 100644 doc/va_architecture.jpg create mode 100644 doc/va_process.jpg diff --git a/README.md b/README.md index 0bd82f24d..d74b09be4 100644 --- a/README.md +++ b/README.md @@ -1,76 +1,678 @@ -[![VA banner](https://raw.githubusercontent.com/asLody/VirtualApp/master/Logo.png)](https://github.com/asLody/VirtualApp) - -[中国人猛戳这里](CHINESE.md "中文") - -About ------ -**VirtualApp** is an open platform for Android that allows you to create a `Virtual Space`, -you can install and run apk inside. Beyond that, VirtualApp is also a `Plugin Framework`, -the plugins running on VirtualApp does not require any constraints. -VirtualApp does **not** require root, it is running on the `local process`. - -NOTICE -------- -This project has been authorized by the business. - -Background ----------- - -VirtualApp was born in early 2015, Originally, it is just a simple plugin framework, -But as time goes on, -the compatibility of it is getting better and better. -in the end, it evolved into a `Virtual Container`. - - -Get started ------------ -If you use latest android studio (version 2.0 or above), please disable `Instant Run`. -Open `Setting | Build,Exception,Deployment`, and disable `Enable Instant Run to hot swap...` - -**Goto your Application and insert the following code:** -```java - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - try { - VirtualCore.get().startup(base); - } catch (Throwable e) { - e.printStackTrace(); - } - } -``` - -**Install a virtual App:** -```java - VirtualCore.get().installApp({APK PATH}, flags); - -``` - -**Launch a virtual App:** -```java - //VirtualApp support multi-user-mode which can run multiple instances of a same app. - //if you don't need this feature, just set `{userId}` to 0. - Intent intent = VirtualCore.get().getLaunchIntent({PackageName}, {userId}); - VActivityManager.get().startActivity(intent, {userId}); -``` - -**Uninstall a virtual App:** -```java - VirtualCore.get().uninstallApp({PackageName}); -``` - -More details, please read the source code of demo app, :-) - -Documentation -------------- - -VirtualApp currently has **no documentation**, If you are interested in VirtualApp, please send email to me. - -License -------- -GPL 3.0 - -About Author ------------- - - Lody (imlody@foxmail.com) +

VA产品说明&开发指导

+ +## VA是什么? ## +VirtualApp(简称:VA)是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。其产品形态为高可扩展,可定制的集成SDK,您可以基于VA或者使用VA定制开发各种看似不可能完成的项目。VA目前被广泛应用于APP多开、小游戏合集、手游加速器、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府数据隔离、手机模拟信息、脚本自动化、插件化开发、无感知热更新、云控等技术领域。
**Github上代码已在2017年12月份停止更新,商业版代码在持续更新中,如需授权获得最新代码,请联系微信:10890** + + +## VA中的术语 ## +术语 | 解释 +---- | --- +宿主 | 集成VirtualApp类库(lib)的App叫做宿主 +宿主插件 | 用于在同一个手机,运行另一种ABI的宿主包,又称做插件包,扩展包,宿主插件包,宿主扩展包 +虚拟App/VApp | VA的虚拟环境多开的app +外部App | 手机真实环境安装的app +
+ +## VA技术架构 ## +![](https://github.com/asLody/VirtualApp/blob/master/doc/va_architecture.jpg) +VA技术一共涉及到了Android的APP层,Framework层以及Native层。 +一个APP想要在Android系统上运行,必须要安装后系统才会接纳。安装到VA内部的APP实际上并没有安装到系统中,所以正常情况下是无法运行的。那如何才能让它运行呢? +答:那就只有“欺骗”系统,让系统认为已经安装。而这个“欺骗”过程就是VA Framework的核心工作内容,也是整个VA的核心技术原理。 + +**下面介绍下在这3个层次分别做了什么事情:** + +层次 | 主要工作 +---- | --- +VA Space | 由VA提供了一个内部的空间,用于安装要在其内部运行的APP,这个空间是系统隔离的。 +VA Framework | 这一层主要给Android Framework和VAPP做代理,这也是VA的核心。VA提供了一套自己的VA Framework,处于Android Framework与VA APP之间。
1. 对于VAPP,其访问的所有系统Service均已被 `VA Framework` 代理,它会修改VAPP的请求参数,将其中与VAPP安装信息相关的全部参数修改为宿主的参数之后发送给Android Framework(有部分请求会发送给自己的VA Server直接处理而不再发送给Android系统)。这样Android Framework收到VAPP请求后检查参数就会认为没有问题。
2. 待Android系统对该请求处理完成返回结果时,VA Framework同样也会拦截住该返回结果,此时再将原来修改过的参数全部还原为VAPP请求时发送的。
这样VAPP与Android系统的交互也就能跑通了。 +VA Native | 在这一层主要为了完成2个工作,IO重定向和VA APP与Android系统交互的请求修改。
1. IO重定向是因为可能有部分APP会通过写死的绝对路径访问,但是如果APP没有安装到系统,这个路径是不存在的,通过IO重定向,则将其转向VA内部安装的路径。
2. 另外有部分jni函数在VA Framework中无法hook的,所以需要在native层来做hook。 +
+ +总结: +通过上面技术架构可以看到,VA内部的APP实际是跑在VA自己的VA Framework之上。 +VA已将其内部APP的全部系统请求进行拦截,通过这项技术也能对APP进行全面控制,而不仅仅只是多开。并且为了方便开发者,VA还提供了SDK以及Hook SDK。 + + +## VA进程架构 # +![](https://github.com/asLody/VirtualApp/blob/master/doc/va_process.jpg) +VA运行时有5类进程:CHILD进程,VA Host Main进程,VA Host Plugin进程,VAPP Client进程,VAServer进程。 +VA为了同时支持32位APP与64位APP,需要安装2个包:一个主包,一个插件包(在本文档中主包是32位,插件包是64位)。 +2个包也是必须的,因为一个包只能运行在一种模式下,要么32位,要么64位。所以对于32位的APP,VA使用32位的主包去运行,对于64位的APP,VA则使用64位的插件包去运行。 +在主包中含了VA的所有代码,插件包中只有一段加载主包代码执行的代码,无其他代码。所以插件包几乎不用更新,只需要更新主包即可。 +另外主包是选择用32位还是64位,可以在配置文件中修改(比如对于要上GooglePlay的用户,会修改为主包64位,插件包32位)。 + +**各类进程的作用与解释如下:**
+ +进程类型 | 作用 +---- | --- +CHILD | 由VA Host集成的其他进程,比如:保活进程,推送进程等。 +VA Host Main | VA主包的UI主界面所在的进程。默认主包是32位,插件包是64位,可在配置文件中修改切换。 +VA Host Plugin | 支持64位APP的插件包所在进程。默认主包是32位,插件包是64位,可在配置文件中修改切换。 +VAPP Client | 安装到VA中的APP启动后产生的进程,在运行时会将io.busniess.va:pxxx进程名修改VAPP的真实进程名。 +VAServer | VA Server的所在的进程,用于处理VA中不交予系统处理的请求。比如APP的安装处理。 +
+ +## VA几乎能满足您的一切需求 ## +通过上面的技术架构,我们可以了解到VA可以对APP进行全面的控制,并且提供了Hook SDK,几乎能满足您在各个领域的一切需求: +1. 可以满足您的**双开/多开**需求 +VA可以让您在同一部手机上安装多个微信/QQ/WhatsApp/Facebook等APP,实现一部手机,多个账号同时登录。 + +2. 可以满足您的**移动安全**需求 +VA提供了一整套内部与外部的隔离机制,包括但不限于(文件隔离/组件隔离/进程通讯隔离),简单的说VA内部就是一个“完全独立的空间”。 +通过VA可将工作事务与个人事务安全的隔离,互不干扰。稍作定制即可实现应用行为审计、数据加密、数据采集、数据防泄漏、防攻击泄密等移动安全相关的需求。 + **2.1 应用行为审计** +通过VA提供的HOOK能力可以实现实时监测用户使用行为,将违规信息上传到服务器;并能轻易实现诸如时间围栏(在某个时间段内能否使用应用的某个功能)、地理围栏(在某个区域内能否使用应用的某个功能)、敏感关键字过滤拦截等功能需求。 + **2.2 数据加密** +通过VA提供的HOOK能力可以实现对应用的全部数据/文件加密,保证数据/文件落地安全。 + **2.3 数据采集** +通过VA提供的HOOK能力可以实现应用数据的实时无感上传需求,如聊天记录、转账记录等,防止事后删除无法追溯。 + **2.4 数据防泄漏** +通过VA提供的HOOK能力可以实现应用防复制/粘贴、防截屏/录屏、防分享/转发、水印溯源等需求。 + **2.5 防攻击泄密** +通过VA提供的应用管控能力可以将APP获取短信/通讯录/通话记录/后台录音/后台拍照/浏览历史/位置信息等隐私相关的行为完全控制在沙盒中,防止木马/恶意APP获取到用户真实的隐私数据,造成泄密等严重后果。 + +3. 可以满足您的**免ROOT HOOK**需求 +VA提供了Java与Native的Hook能力,通过VA,您可以轻易实现诸如虚拟定位、改机、APP监控管理、移动安全等各种场景需要的功能。 + +4. 可以满足您的**APP静默安装**需求 +VA提供了APP静默安装,静默升级,静默卸载的能力。如应用商店或游戏中心在集成VA后可以避免需要用户手动点击确认安装的操作,做到下载后立即安装到VA内,给用户带来“小程序”搬的体验,彻底避免了应用不易被用户安装上的问题。 + +5. 可以满足您的**APP管控**需求 +您可以通过VA清楚的掌握APP访问了哪些系统API,哪些敏感数据,哪些设备信息等。比如APP是否访问了联系人,相册,通话记录,是否访问了用户的地理位置等信息。 +当然,您还可以通过VA控制或者构造自定义的信息给这些APP。不仅于此,您还可以获取到APP的私有数据,比如聊天数据库等。总之通过VA提供的应用管控能力,您可以轻易控制APP的一切行为,甚至修改APP与服务器交互内容等。
+ + +6. 可以满足您的**海外市场**需求 +VA实现了对Google服务的支持,以支持海外的App运行,比如Twitter、Messenger、WhatsApp、Instagram、FaceBook、Youtube等。 + +7. 可以满足您**几乎一切能想到**的需求 +VA对于内部的App具有完全的监管和控制能力,几乎能满足您的一切需求! + +8. 同时VA也是该技术领域__唯一一款__对外商业授权的产品 +截止目前已有**上百家**授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP__日启动__次数__超过2亿次__,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,不断提升产品性能与兼容性! + + +VA的特有能力 +--- + +- 克隆能力
+可以克隆外部系统中已经安装的App,并在内部运行,互不干扰。典型应用场景为App双开。 + +- 免安装能力
+除了克隆已安装之外,VA可以直接在内部安装(外部无感知)apk,并在内部直接运行。典型应用场景为插件化,独立应用市场等。 + +- 多开能力
+VA不仅可以“双开”,独特的多用户模式支持用户在内部无限多开同一个App。 + +- 内外隔离能力
+VA是一个标准的沙盒,或者说“虚拟机”,提供了一整套内部与外部的隔离机制,包括但不限于(文件隔离/组件隔离/进程通讯隔离),简单的说VA内部就是一个“完全独立的空间”。在此基础之上,稍作定制即可实现一部手机上的“虚拟手机”。当然您也可以发挥想象,定制成应用于数据加密,数据隔离,隐私保护,企业管理的应用系统。 + +- 对于内部App的完全控制能力
+VA对于内部的App具有完全的监控和控制能力,这点在未Root的外部环境中是绝对无法实现的。 +
+详细(下拉打开) + 1. 服务请求控制,首先VA直接提供了一些服务请求的拦截,您可以在集成VA的时候方便的定制这些服务请求,包括但远不限于(App请求安装apk/App请求打开某些文件/App请求定位数据/App请求手机信息等等)

+ 2. 系统API控制,VA虚拟并实现了整个安卓系统框架,这也是VA可以免安装在内部运行apk的原理,您可以对虚拟框架的实现进行修改以动态监测分析App的行为等;除此之外,您还可模拟一些系统行为以实现一些在外部难以实现的需求(例如游戏手柄)。

+ 3. 内存读写,VA可以无需Root读写内部App进程的内存。

+ 4. 免Root调试,VA可以免Root调试(ptrace)内部的App进程,基于此您还可以实现免Root的进程注入。

+ 5. 加载任意“插件”和“行为”,VA内部的App进程由VA的框架Client端代码派生而来,所以您可以在进程的入口代码插入任何“加载”以及“控制”逻辑。这些实现都非常简单。

+ 6. 方法Hook,VA内置了一套运行于Android各个版本(直到AndroidQ)的Xposed框架以及native hook框架,基于此您可以方便的Hook任意内部App的任意Java/Native方法。可以轻松实现一个免Root的Xposed环境(有实例代码)。

+ 7. 文件控制,VA内置了完整的文件重定向,可以方便的控制内部App的文件的读写,基于此可以实现对文件的保护加密等功能。

+ 8. 注:以上控制能力均有实现代码或者实例以作参考。 +
+ + +VA的其他特性 +--- + +- 高性能
+进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 + +- 全版本支持
+支持5.0-12.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 + +- 易扩展与集成
+VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 + +- 支持Google服务
+提供Google服务的支持,以支持海外的App + + +## VA与其他技术方案对比 ## +在做企业级移动安全时,往往需要对APP进行管控,以下是列出的可能技术方案对比: + +技术方案 | 原理简介 | 点评 | 运行性能 | 兼容稳定性 | 项目维护成本 +---- | --- | --- | --- | --- | --- +二次打包 | 通过反编译目标APP,加入自己的控制代码,重新打包 | 1.现在的APP几乎都有加固或防篡改保护,重打包已是一件非常困难的事
2.手机系统也会检测APP是否被重打包,如果重打包,会直接提示用户存在安全风险,甚至不让安装
3.针对每一个APP,甚至每一个版本都要深入去逆向分析,耗时耗力,难于维护 | 优秀 | 差 | 高 +定制ROM | 通过定制系统源码,编译刷到指定手机 | 只能针对指定的内部手机,局限性太大,无法扩展 | 优秀 | 优秀 | 高 +ROOT手机 | 通过ROOT手机,刷入xposed等类似框架 | 1.ROOT手机现在本身已是一件不太可能的事
2.现实中也很难让用户能去ROOT自己的手机 | 优秀 | 差 | 高 +VA | 轻量级虚拟机,速度快,对设备要求低 | 无上述风险点 | 优秀 | 优秀,有上百家企业在同时测试反馈 | 低,VA提供了API并有专业的技术团队保障项目稳定运行 +
+通过以上对比可以看出,VA是一款优秀的产品,并且能降低您的开发维护成本! + +## 集成VA步骤 ## +第1步:在您的Application中调用VA接口```VirtualCore.get().startup()```来启动VA引擎 +第2步:调用VA接口```VirtualCore.get().installPackageAsUser(userId, packageName)```将目标APP安装到VA中 +第3步:调用VA接口```VActivityManager.get().launchApp(userId, packageName)```启动APP +**仅通过以上3个API就完成了基础使用,VA已屏蔽了复杂的技术细节,并提供了接口API,让您的开发变得很简单!** + +## VA的兼容稳定性 ## +VA已被**上百家**企业进行了广泛测试,包含**数十家上市公司高标准**的测试及反馈,几乎涵盖了海内外的各种机型设备和场景! +为您的稳定运行提供了充分的保障! + +截止目前,支持的系统版本: + +系统版本 | 是否支持 +---- | --- +5.0 | 支持 +5.1 | 支持 +6.0 | 支持 +7.0 | 支持 +8.0 | 支持 +9.1 | 支持 +10.0 | 支持 +11.0 | 支持 +12.0 | 支持 +
+ + +支持的APP类型: + +APP类型 | 是否支持 +---- | --- +32位APP | 支持 +64位APP | 支持 +
+ +支持的HOOK类型: + +Hook类型 | 是否支持 +---- | --- +Java Hook | 支持 +Native Hook | 支持 + +支持的CPU类型: + +Hook类型 | 是否支持 +---- | --- +ARM 32 | 支持 +ARM 64 | 支持 +
+ +## 集成VA遇到问题如何反馈? ## +购买授权后我们会建立微信群,有任何问题可以随时反馈给我们,并根据优先级在第一时间处理! + +## VA开发文档 ## +VA开发文档请参考:[开发文档](https://github.com/asLody/VirtualApp/blob/master/doc/VADev.md) + + + +授权说明 +------ +VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,于2015年至2021年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当年的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` + +
+负责人:张总
+手机:130-321-77777
+微信:10890
+
+ + +严重声明 +------ +您如果未经授权将VirtualApp用于**内部使用、商业牟利或上传应用市场**,我们将取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。`购买商业授权为您节省大量开发、测试和完善兼容性的时间,让您更多时间用于创新及盈利。`罗盒科技已在2020年报警和起诉了一些个人及公司。
+ +**为响应国家对于知识产权的保护号召!凡举报自己所在公司或其他公司未经授权,违法使用VirtualApp代码开发产品的,一经核实给予现金奖励。我们会对举报人身份保密!举报联系微信:10890** + +
+ + +代码更新 +------ + +**2021年 9月21号 至 2021年 10月10号 商业版代码更新内容** + +356、修复11.0上GMS登录问题
+355、修复11.0 部分APP读写sdcard报错的问题
+354、修复va core进程死亡后,APP可能打不开的问题
+353、增加未安装插件时无法启动的错误日志
+ + +**2021年 8月22号 至 2021年 9月20号 商业版代码更新内容** + +352、横屏重新适配
+351、修复部分APP通过file协议安装后无法打开的问题
+350、修复传递给JobIntentService中Intent数据丢失问题
+349、修复JobIntentService第二次调用无法工作的问题
+348、修复华为手机上某些APP奔溃的问题
+347、修复小米手机上游戏登录问题
+346、修复某些应用加固后无法打开的问题
+345、增加对关联启动权限检测
+344、targetSdk 30适配
+343、修复targetSdk为30时,某些应用无法上网的问题
+342、修复targetSdk为30时,sdcard无法访问的问题
+341、编译脚本中使用cmake替换gradle task
+340、移除过时文档
+ +**2021年 8月7号 至 2021年 8月21号 商业版代码更新内容** + +349、调整优化gradle脚本
+348、hidedenApiBypass支持Android R+
+347、targetSdk 30 支持
+346、修复VIVO系统服务bug
+345、修复VIVO手机无法使用摄像头的bug
+344、修复dex加载异常状态的获取
+343、修复Android R上libart.so路径问题
+342、修复Andoid Q+ 删除通知的bug
+341、修复APN uri的权限检查
+340、修复Android R暂停恢复线程状态
+339、修复debug模式下部分hook失效情况
+338、修复hook在R之后的一些bug
+ +**2021年 4月25号 至 2021年 8月6号 商业版代码更新内容** + +337、修复探探部分手机不能上传头像问题
+336、修复Android 10 华为设备IO重定向问题
+335、调整横竖屏逻辑,减少异常情况发生
+334、添加Activity生命周期的回调接口
+333、修复Android 12的广播问题
+332、修复微信部分界面状态异常的BUG
+331、修复Outlook、One drive、Teams、Zoom等海外app的支持
+330、修复Android 11 一个权限请求BUG
+329、修复部分cocos2d引擎只显示半屏的问题
+328、修复微信在多用户下不能发送文件的问题
+327、split apk 支持
+326、Android S 支持
+ +**2021年 2月24号 至 2021年 4月24号 商业版代码更新内容** + +325、适配多用户环境
+324、修复新版微信的兼容问题
+323、兼容更多企业级加固
+322、支持VAPP设置电源优化
+321、修复缺失权限声明
+320、修复Android 11上android.test.base库的引用
+319、优化ext插件判断
+318、优化安装时ABI的选择
+317、修复Google文档在Android 11上崩溃的问题
+ +**2020年 10月15号 至 2021年 2月23号 商业版代码更新内容** + +316、解决新版爱加密、邦邦等加固的兼容性
+315、修复WhatsApp不显示冷启动Splash的问题
+314、优化对系统app的识别
+313、完善多用户环境下的支持
+312、解决ext插件部分情况下卡死的问题
+311、支持Google Play在容器中下载APP
+310、修复Android 11 QQ无法显示图片的问题
+309、兼容Android 11运行Google Service
+308、解决Android 11无法运行chromium
+307、支持Hook @CriticalNative Method
+306、修复JDK 13无法编译运行的问题
+305、修复Service部分情况可能crash的问题
+304、修复Android 11无法加载外部存储私有数据的问题
+303、修复低版本app无法使用org.apache.http.legacy的问题
+302、修复某些情况系统任务栈只显示最后一个的问题
+301、完善不同平台的构建脚本
+300、修复Android 11无法读取obb的问题
+299、解决软件无法向后兼容的问题
+298、重构VApp安装框架
+297、重构virtual文件系统
+296、修复某些情况下WebView无法启动的问题
+295、修复VApp卸载重装的BUG
+294、修复LOL手游的登录异常问题
+293、支持安装Splits APK
+292、支持动态配置主包环境
+291、修复32位QQ调用64位微信卡顿的问题
+290、修复Messenger调用Facebook崩溃的问题
+289、优化对Google服务框架的支持
+288、实现新的扩展包同步机制
+287、修复Android 11正式版的异常问题
+286、添加系统Package缓存,优化性能
+285、修复disabled组件还能被PMS查询的BUG
+284、修复微信部分界面Launch行为异常的问题
+283、修复ContentProvider.getCallingPackage返回Host包名的BUG
+282、修复uid虚拟化的BUG,解决部分app权限检查失败的问题
+281、重写PendingIntent, IntentSender的实现
+280、优化进程管理,修复长期存在的概率性进程死锁问题
+279、重写Service实现,Service生命周期更准确,不容易被杀死
+ + +**2020年 9月13号 至 2020年 10月15号 商业版代码更新内容** + +278、修复 64 位 App 无法调用 32 位 App 的问题
+277、修复 Android R 加载 HttpClient 的问题
+276、修复 Android R debug 模式下的崩溃问题
+ +**2020年 8月23号 至 2020年 9月12号 商业版代码更新内容** + +275、添加缺失的 service hook
+274、修复百度翻译无法启动的问题
+273、修复 GP 下载的 split app 无法启动的问题
+ +**2020年 7月10号 至 2020年 8月22号 商业版代码更新内容** + +272、修复 Service 创建
+271、添加 NotificationService 缺失的 Hook
+270、修复 Yotube 崩溃
+ +**2020年 5月19号 至 2020年 7月9号 商业版代码更新内容** + +269、初步适配 Android 11 beta1
+268、修复小红书多开闪退的问题
+267、修复某些 App 多开报“应用签名被篡改”的问题
+ +**2020年 4月24号 至 2020年 5月18号 商业版代码更新内容** + +266、修复 sh 调用错误
+265、修复 9.0 以上最新版 Facebook 无法登陆的问题
+264、帮助企业微信修复启动虚拟存储的情况下无法拍照的问题
+263、修复某些情况下 64位 app 打不开 Activity 的问题
+ +**2020年 3月24号 至 2020年 4月23号 商业版代码更新内容** + +262、修复 Vivo 设备提示安装游戏 SDK 的问题
+261、修复 Android Q 无法加载部分系统 so 的问题
+260、修复华为设备微博未响应
+259、忽略不必要的权限检查造成的崩溃
+258、修复 WPS 分享文件崩溃的问题
+257、部分 10.0 设备的闪退问题
+ +**2020年 3月7号 至 2020年 3月23号 商业版代码更新内容** + +256、修复微信同时打开两个页面问题
+255、修复微信登陆成功但是返回登陆页面的问题
+254、修复最新版 QQ 无法下载附件的问题
+253、更新 SandHook 版本
+252、修复 9.0 以上安装未签名Apk问题
+251、修复 10.0 的定位问题
+ +**2020年 1月16号 至 2020年 3月6号 商业版代码更新内容** + +250、调整 lib 重定向逻辑
+249、修复三星 10.0 系统上的崩溃问题
+248、修复 release build 的 hook 异常
+247、增加 SandHook 的 proguard 规则
+246、修复对部分 App 中 VirtualApk 的兼容问题
+245、修复 VA 内部请求安装 apk 失败的问题
+ +**2019年 12月26号 至 2020年 1月15号 商业版代码更新内容** + +244、修复 Android Q 遗漏的 hook
+243、禁用 Emui10 的 AutoFill
+242、增加新 api 结束所有 activity
+ +**2019年 12月15号 至 2019年 12月25号 商业版代码更新内容** + +241、修复 Emui10 上企业微信等 App 无法启动的问题
+240、修复在 4.x 可能导致的崩溃
+239、升级 SandHook 修复对 Thread 类的 Hook
+238、修复 Android Q 某些接口导致的权限问题
+ +**2019年 11月20号 至 2019年 12月14号 商业版代码更新内容** + +237、修复 Notification 缓存导致的崩溃
+236、修复高版本 Notification 的 classloader 问题
+ +**2019年 11月9号 至 2019年 11月19号 商业版代码更新内容** + +235、修复 Android 5.x 的 ART Hook
+234、修复 ART Hook 可能导致的死锁问题
+ +**2019年 11月2号 至 2019年 11月8号 商业版代码更新内容** + +233、修复 WPS, 网易邮箱等在 Q 设备上崩溃的问题
+232、修复汤姆猫跑酷在部分 Q 设备上崩溃的问题
+231、修复 QQ 在部分 Q 设备上崩溃的问题
+ +**2019年 10月25号 至 2019年 11月1号 商业版代码更新内容** + +230、修复克隆 Google Play 下载的 64位 App
+229、修复企业微信
+228、修复 Telegram
+ +**2019年 10月8号 至 2019年 10月24号 商业版代码更新内容** + +227、修复 Android P 下 AppOspManager 的异常
+226、添加 Android P 下 ActivityTaskManager 丢失的 Hook
+225、修复 Android P 下 Activity Top Resume 异常
+224、支持在系统多用户模式下运行!
+ +**2019年 10月8号 商业版代码更新内容** + +223、修复Android P 以上内部 app 返回桌面异常的问题
+222、64位分支支持 Android Q
+ +**2019年 9月20号 至 2019年 10月7号 商业版代码更新内容** + +221、修复安装在扩展插件中的 apk 无法正确显示图标和名称的问题
+220、修复 twitter 无法打开的问题
+219、正式兼容 Android Q 正式版!
+218、修复 Android Q 某些 Activity 无法再次打开的问题
+217、初步适配 Android Q 正式版
+216、修复数个64位分支的 Bug
+215、新增加支持32位插件的64位分支,该分支支持32位旧设备并且64位设备在32位插件的情况下可以支持32位旧应用
+ +
+2018年 1月1日 至 2019年 7月 30 日 商业版代码更新内容(下拉打开) +214、改进 App 层提示信息
+213、改进部分编码
+212、修复从宿主向插件发送广播的方法
+211、兼容最新版 gradle 插件
+210、增加广播命名空间以避免多个使用 VA 技术的 App 互相干扰
+209、修复 IMO 打不开的问题
+208、修复部分 ContentProvider 找不到的问题
+207、支持纯32位模式,以兼容老设备
+206、初步支持纯64位模式,以应对8月份的谷歌市场的策略变化
+205、适配到 Android Q beta4
+204、修复了货拉拉无法安装的问题
+203、优化了64位apk的判定逻辑
+202、修复配置网络证书的 App 的联网
+201、重构组件状态管理
+200、优化 MIUI/EMUI ContentProvider 兼容性
+199、修复 StorageStats Hook
+198、修复快手无法登陆
+197、修复 YY 无法启动,更好的兼容插件化框架
+196、修复 Facebook 登陆
+195、修复 Google Play 下载的 App 无法找到 so 的问题(皇室战争)
+194、修复 split apk 支持
+193、修复 Youtube 无法启动
+192、修复优酷无法启动的问题
+191、修复多开时app间可能存在广播namespace冲突的BUG
+190、采用新的策略绕过Android P以后的Hidden Policy API
+189、适配Android Q(beta1)
+188、修复华为设备部分app无法识别存储的问题
+187、修复启动进程可能失败导致app无法运行的问题
+186、修复4.4设备部分native符号无法找到的问题
+185、修复部分设备WebView包名获取失败的问题
+184、修复Service细节处理的问题
+183、优化启动速度
+182、修复WebView在少数机型加载失败的情况
+181、修复Lib决策的问题
+180、修复部分华为机型无法读取内存卡的问题
+179、修复Service可能存在的问题
+178、允许根据intent判断Activity是否在外部启动
+177、修复部分机型上Gms和Google Play启动到了不正确的环境
+176、修复新实现的StaticBroadcast导致的兼容性问题
+175、修复Android P上无法使用apache.http.legacy的问题
+174、实现Native trace
+173、优化IO Redirect性能
+172、修复wechat部分时候出现网络无法连接的问题
+171、修复小概率process attach不正确的BUG
+170、开始下一阶段的ROADMAP
+169、解决Android P无法注册超过1000个广播导致的问题
+168、修复可能导致ANR的DeadLock
+167、修复部分app动态加载so失败的问题
+166、修复免安装运行环境下部分机型第一次打开出现黑屏的问题
+165、兼容适配多款主流的Android模拟器
+164、优化启动性能
+163、解决多个内存泄露问题
+162、修复IO Redirect优先级的问题
+161、修复8.0以下设备Messenger无网络连接的问题
+160、修复双开时外部app卸载时内部app仍然保留的BUG
+159、修复部分腾讯加固无法运行的问题
+158、修复Instagram无法登录Facebook的BUG
+157、修复进程小概率可能重复启动的BUG
+156、修复GET_PERMISSIONS没有获取权限的BUG
+155、修复startActivityIntentSender的BUG
+154、修复vivo设备部分Activity无法启动的问题
+153、修复app无法调用外部app选择文件的问题
+152、完善Android P的兼容
+151、兼容Android P的Google服务
+150、解决Messenger部分功能异常
+149、完善IO Redirect
+148、大量适配Gms, 修复Gms运行过程中进程无限重启的问题
+147、重新实现Service的运行机制
+146、完善64bit,提供了部分ROM配置64bit Engine权限的API
+145、修复了4.4设备上的Activity启动问题
+144、支持excludeFromRecent属性
+143、修复Instagram无法Facebook登录的问题
+142、修复Facebook第一次登录闪退的问题
+141、支持以64位模式运行Gms、Google play、Play game
+140、支持在双开/免安装运行的Google play中下载和安装app
+139、修复DownloadManager的BUG
+138、修复Google play返回上层时重启界面的BUG
+137、修复免安装模式下so决策问题
+136、优化构建脚本,便于引入项目
+135、修复移动MM SDK无法启动的问题
+134、修复微信摇一摇的BUG
+133、修复中兴设备不稳定的BUG
+132、支持ARM64下的IO Redirect
+131、修复USE_OUTSIDE模式下外部app更新时,内部app没有更新的BUG
+130、兼容最新Android 9.0(代号: pie) 及正式版之前发布的四个Preview版本
+129、兼容内置houdini的x86设备
+128、WindowPreview技术,使app启动与真实app达到一样的速度
+127、新的ActivityStack以提高app运行质量
+126、解决接入Atlas Framework的app运行异常的问题
+125、现在可以定义虚拟app返回桌面的具体行为
+124、现在双开模式下app随系统动态更新,不需要手动检查
+123、支持targetSdkVersion >= 26时仍可正常运行低版本的app
+122、兼容腾讯游戏管家的QDroid虚拟引擎 (beta)
+121、大量重构底层代码,大幅提升运行速度
+120、修复网易新闻分享到微博后无法取消的问题
+119、修复App自定义权限无法识别的问题
+118、修复墨迹天气app无法启动的问题
+117、修复部分政府app无法启动的问题
+116、API的变动详见代码
+115、修复三星系列应用的相互调用问题
+114、修复小米应用在非小米系统的账号问题
+113、修复分享/发送等第三方调用,返回页面不正常
+112、修复应用宝提示不能安装
+111、调用第三方app,对uri进行加密
+110、适配前刘海
+109、适配小米rom的hook
+108、适配努比亚录音问题
+107、内部悬浮窗权限控制
+106、优化自定义通知栏的处理
+105、修复Context的INCLUDE_CODE权限问题
+104、适配华为,oppo的角标
+103、修复百度视频的进程重启问题
+102、修复某些snapchat的无法启动问题
+101、适配autofill服务,例如piexl系列
+100、完善64位的io hook
+99、优化hook库的兼容性,加回dlopen
+98、64位扩展包的so移到32位主包。(jni代码改动后,在Run之前,请先build一次)
+97、通知栏改动:适配8.1的通知渠道;移除应用时,移除应用的全部通知
+96、兼容部分app,需要设置android:largeHeap=true
+95、修复ffmpeg库的视频无法播放问题
+94、优化横竖屏切换
+93、降低通过Intent.ACTION_VIEW调用外部Activity限制。
+92、兼容MG SDK
+91、64位支持还在开发阶段
+90、更新混淆配置app/proguard-rules.pro,必须加规则-dontshrink
+89、优化模拟机型,例如:模拟后,某些app不出现设备验证
+88、提高dex2oat兼容性
+87、优化模拟定位
+86、移除dlopen
+85、targetVersion可以改为26:支持targetVersion<23的app动态权限申请,支持targetVersion<24的文件Uri
+84、installPackage改为默认异步形式
+83、为了支持64位模式,换回aidl
+82、去掉SettingHandler现在可以动态设置特殊规则,规则会存储,不需要重复设置
+81、增加2个native_setup
+80、提高jobService兼容性
+79、ShortcutService相关:关联VASettings.ENABLE_INNER_SHORTCUT
+78、为了稳定性和运行效率,去掉上个版本的蓝牙,wifi,不声明权限的适配。
+77、增加app启动异常的广播Constants.ACTION_PROCESS_ERROR
+76、修复少数游戏横屏判断问题
+75、demo增加机型模拟
+74、适配vivo一个自定义权限(后台弹窗)VA是把一个历史acitivty返回前台,vivo需要这个权限。
+73、如果没有蓝牙权限,返回默认值(海外用)
+72、修复uid权限检查问题
+71、安全性更新,内部应用的文件权限控制
+70、提高内部app调用的兼容性,第三方登录,分享
+69、自动过滤没权限的外部ContentProvider
+68、增加功能:内部app的权限检查(默认关闭)
+67、机型模拟:Build类和build.prop
+66、提高对乐固加固的app兼容性
+65、适配三星wifimanager
+64、修复ipc框架一个参数传递问题(IPCMethod这个类必须更新)
+63、补全7.0通知栏的hook
+62、修正8.0动态快捷菜单的hook
+61、SettingHandler新增一个适配接口,主要适配各种游戏
+60、功能改动:google自动安装改为手动安装,避免第一次启动时间过久
+59、可以禁止访问外部某个ContentProvider
+58、适配华为桌面图标数量
+57、权限分类注释,标注可删除权限。
+56、增加双开模式的app跟随外部升级的开关。
+55、提高app的jni兼容性。
+54、提高对app集成其他插件框架的兼容性。
+53、增加设置接口,根据包名进行设置。
+52、增加Uri的适配范围,支持通过Uri分享和查看文件。
+51、修复一个在三星8.0的问题。
+50、提高对系统自带的app组件兼容性,更好兼容chrome webview,google service。
+49、提高ART稳定性
+48、增加相机适配范围
+47、支持内部App在8.0下的快捷方式管理
+46、修复exec异常
+45、提高稳定性(修复微信登录闪退)
+44、解决微信数据库崩溃问题
+43、修复部分4.4设备崩溃问题
+42、修复后台应用易被杀死,土豆视频黑屏,新浪微博无法打开,优酷两次返回无法退出。
+41、增加应用的保活机制,双开APP更不易被杀死。
+40、优化虚拟引擎启动性能。
+39、兼容了大部分的加固,第三方APP兼容性对比上一版提升40%+。
+38、修复某些rom下,快捷方式图标不正确
+37、兼容以前组件StubFileProvider
+36、适配部分新ROM的虚拟IMEI
+35、改善进程初始化代码,增加稳定性
+34、添加内部发送Intent.ACTION_BOOT_COMPLETED的广播,可以设置开关
+33、适配关联google play游戏,支持游戏使用google登录
+32、适配android O的google service框架
+31、适配android O 快捷方式
+30、适配耳机模式
+29、某些rom对intent的大小限制,demo添加缩放快捷方式图标代码
+28、修复多开情况下一个bug
+27、修复某些情况下MediaController的bug
+26、修复4.1.2的StubFileProvider报错
+25、分享的uri处理
+24、修复跨app调用Activity的回调
+23、前台服务的通知栏拦截开关
+22、附带doc
+21、完善VA内部的intent的CHOOSE回调
+20、Android O的通知栏适配2
+19、ipc框架优化, 提高判断binder的存活准确性
+18、jni的log开关 Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE
+17、混淆配置
+16、Android O的通知栏适配
+15、修复部分app网络卡的问题
+14、适配 android 8.0的dl_open(jni加载)
+13、修复华为emui8.0的一个bug
+12、完善定位
+11、设置手机信息,imei伪装算法
+10、适配8.0某个功能(主要app:whatsapp)
+9、修复内部微信等应用,无法更新图片,视频
+8、demo增加安装监听,自动升级克隆模式的应用
+7、7.0的file provider适配
+6、增加了定位代码
+5、代码进行了架构优化
+4、与开源版不同的特征
+3、解决了微信被封的一些问题
+2、修复了部分机型兼容性
+1、修复了12个小BUG
+
+ + + + + + diff --git a/doc/1.png b/doc/1.png new file mode 100644 index 0000000000000000000000000000000000000000..a4c7c303a86457ebc827355410d2dff990514ddc GIT binary patch literal 19412 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°fi*`S#@fdAGAOH!xE&-Y5G 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 literal 0 HcmV?d00001 diff --git a/doc/3_1.png b/doc/3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..70c597f1322d5099862ab944f9bb0b68616a8051 GIT binary patch literal 23584 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 literal 0 HcmV?d00001 diff --git a/doc/3_5.png b/doc/3_5.png new file mode 100644 index 0000000000000000000000000000000000000000..2e17bc0569dd887c07647f6cc4a4935c8164caa8 GIT binary patch literal 104820 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

VA基础开发文档

+ +本文档主要介绍2部分。 +第一部分是VA的源码结构介绍,这部分是为了让开发者能快速了解掌握VA源码框架。 +第二部分是VA的基础SDK使用说明。 +其他更多的开发文档见:[VA私有库Wiki](https://github.com/asLody/VirtualApp-Priv/wiki) +VA产品说明:[文档](https://github.com/asLody/VirtualApp/blob/master/VA.md) +
+ +**下面开始第一部分,VA源码结构介绍:** + +## 1. VA源码目录介绍 ## +下图是VA源码根目录: +![](https://github.com/asLody/VirtualApp/blob/master/doc/1.png) +可以看到VA一共有4个源码目录,各个目录介绍如下: + +目录名称 | 作用 +---- | --- +app | VA Demo主包源码所在目录 +app-ext | VA Demo插件包源码所在目录 +lib | VA库源码所在目录 +lib-ext | VA插件库源码所在目录 +
+ +## 2. VA编译配置文件介绍 ## +VA的编译配置文件是VAConfig.gradle: +![](https://github.com/asLody/VirtualApp/blob/master/doc/2_1.jpg) + +配置解释: + +配置名称 | 作用 +---- | --- +PACKAGE_NAME | 用于配置VA主包的包名 +EXT_PACKAGE_NAME | 用于配置VA插件包的包名 +VA_MAIN_PACKAGE_32BIT | 用于配置VA主包是32位还是64位,true为32位,false为64位 +VA_ACCESS_PERMISSION_NAME | 用于配置VA中4大组建的权限名称 +VA_AUTHORITY_PREFIX | 用于配置VA主包中ContentProvider的authorities +VA_EXT_AUTHORITY_PREFIX | 用于配置VA插件包中ContentProvider的authorities +VA_VERSION | 用于配置VA库版本,开发者一般不需要关心 +VA_VERSION_CODE | 用于配置VA库版本代码,开发者一般不需要关心 +
+ +## 3. VA核心代码解释 ## +1. `com.lody.virtual.client`包下的代码运行在VAPP Client进程中,主要用于VA Framework中的APP Hook部分,完成对各个Service的HOOK处理 +![](https://github.com/asLody/VirtualApp/blob/master/doc/3_1.png) +2. `com.lody.virtual.server`包下的代码运行在VA Server进程中,代码主要用于VA Framework中的APP Server部分,实现处理APP安装以及其他不给Android系统处理的APP请求 +![](https://github.com/asLody/VirtualApp/blob/master/doc/3_2.png) +3. `mirror`包下的代码主要用于对系统隐藏类的引用,属于工具类,减少大量反射代码的编写 +![](https://github.com/asLody/VirtualApp/blob/master/doc/3_3.png) +4. `cpp`包下的代码进行在VAPP Client进程中,主要用于VA Native部分,实现IO重定向和jni函数HOOK。其中: + - `substrate`中实现了针对arm32和arm64的hook + - `vfs.cpp`中实现了VA的虚拟文件系统,用于控制APP文件访问限制 + - `syscall_hook.cpp`中实现了对IO的Hook +![](https://github.com/asLody/VirtualApp/blob/master/doc/3_4.png) +5. `DelegateApplicationExt.java`运行在VA Host Plugin进程中,用于VA插件包,实现了对主包代码的加载执行 +![](https://github.com/asLody/VirtualApp/blob/master/doc/3_5.png) + +

+**下面开始第二部分,VA SDK使用介绍:** + +## 1. VA工程接入 ## +### 用Android Studio打开VirtualApp-Priv项目 + +可见多个模块: +* app +* app-ext +* lib +* lib-ext + +其中**lib**和**lib-ext**属于VirtualApp`核心库`以及`扩展库`,**app**和**app-ext**则属于`示例app`。 + + + +### 创建自己的App +新建一个application类型的module,并添加lib模块为依赖 +```gradle +implementation project(':lib') +``` + +### 根据需求修改VAConfig.gradle: +```gradle +ext { + VA_MAIN_PACKAGE_32BIT = true // 主包为32位 + VA_ACCESS_PERMISSION_NAME = "io.busniess.va.permission.SAFE_ACCESS" // VirtualApp组件用到的权限名称 + VA_AUTHORITY_PREFIX = "io.busniess.va" // VirtualApp中ContentProvider用到的authority,不能与其他app重复 + VA_EXT_AUTHORITY_PREFIX = "io.busniess.va.ext" // VirtualApp扩展包中ContentProvider用到的authority,不能与其他app重复 + // ... +} +``` + +### 在AndroidManifest.xml添加所需的权限 +```xml + +``` +权限名称必须与**VAConfig.gradle**中所声明的保持一致,可以在**build.gradle**中添加**Placeholder**来防止出错。 + +``` gradle +android { + // ... + manifestPlaceholders = [ + VA_ACCESS_PERMISSION_NAME: rootProject.ext.VA_ACCESS_PERMISSION_NAME, + ] +} +``` + +### 创建一个Application + +#### 复写attachBaseContext方法,添加引导VirtualApp的代码: + +```java + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + try { + VirtualCore.get().startup(base, mConfig); + } catch (Throwable e) { + e.printStackTrace(); + } + } + +``` + +#### 这里传入了一个VirtualApp的一个配置 mConfig +```java +private SettingConfig mConfig = new SettingConfig() { + @Override + public String getMainPackageName() { + // 主包的包名 + return BuildConfig.APPLICATION_ID; + } + + @Override + public String getExtPackageName() { + // 扩展包包名 + return BuildConfig.EXT_PACKAGE_NAME; + } + + @Override + public boolean isEnableIORedirect() { + // 是否启用IO重定向,建议开启 + return true; + } + + @Override + public Intent onHandleLauncherIntent(Intent originIntent) { + // 回到桌面的 Intent 拦截操作,这里把回到桌面的动作改成回到主包的BackHomeActivity页面 + Intent intent = new Intent(); + ComponentName component = new ComponentName(getMainPackageName(), BackHomeActivity.class.getName()); + intent.setComponent(component); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return intent; + } + + @Override + public boolean isUseRealDataDir(String packageName) { + // data路径模拟真实路径格式,需要启用IO重定向。部分加固会校该验路径格式 + return false; + } + + @Override + public boolean isOutsidePackage(String packageName) { + // 是否是外部app。 设置外部 app 对内部app看见 + return false; + } + + @Override + public boolean isAllowCreateShortcut() { + // 是否允许创建桌面快捷图标。建议关闭(false),自己实现桌面快捷方式 + return false; + } + + @Override + public boolean isHostIntent(Intent intent) { + // 是否由VirtualApp处理的Intent + return intent.getData() != null && "market".equals(intent.getData().getScheme()); + } + + @Override + public boolean isUseRealApkPath(String packageName) { + // 安装apk路径模拟真实路径,需要启用IO重定向。部分加固会校验该路径格式 + return false; + } + + @Override + public boolean isEnableVirtualSdcardAndroidData() { + // 启用外置存储下的 `Android/data` 目录的重定向 + // 需要重定向支持 + // Android 11 之后必须启用!! + return BuildCompat.isR(); + } + + @Override + public String getVirtualSdcardAndroidDataName() { + // 设置外置存储下的 `Android/data` 目录的重定向路径 + // /sdcard/Android/data/com.example.test/ ==>> /sdcard/{VirtualSdcardAndroidDataName}/{user_id}/Android/data/com.example.test/ + return "Android_va"; + } + + @Override + public FakeWifiStatus getFakeWifiStatus() { + // 修改wifi信息。 null 则不修改 + return null; + } + + @Override + public boolean isHideForegroundNotification() { + // 隐藏前台消息,不建议隐藏 + return false; + } + + @Override + public boolean isOutsideAction(String action) { + // 外部 Intent 的 action 事件响应 + return MediaStore.ACTION_IMAGE_CAPTURE.equals(action) + || MediaStore.ACTION_VIDEO_CAPTURE.equals(action) + || Intent.ACTION_PICK.equals(action); + } + + @Override + public boolean isDisableDrawOverlays(String packageName) { + // 禁用 VAPP 的顶层覆盖(浮窗)。 + return false; + } + }; +``` + +### 复写onCreate,添加初始化VirtualApp的代码: +```java + @Override + public void onCreate() { + super.onCreate(); + VirtualCore virtualCore = VirtualCore.get(); + virtualCore.initialize(new VirtualCore.VirtualInitializer() { + @Override + public void onMainProcess() { + // 主进程回调 + } + + @Override + public void onVirtualProcess() { + // 虚拟App进程回调 + } + + @Override + public void onServerProcess() { + // 服务端进程回调 + } + + @Override + public void onChildProcess() { + // 其他子进程回调 + } + }); + } + +``` + +由于VirtualApp会启动多个进程,所以Application会进入N次,不同的进程会走到VirtualInitializer不同的回调,可以在这里根据进程类型添加额外的初始化代码。 + +## 2. 安装APP ## +## API: +```java +VirtualCore.java + + public VAppInstallerResult installPackage(Uri uri, VAppInstallerParams params); +``` +## 参数Uri是什么? +Uri决定了**需要安装的apk**的来源,目前支持 package 和 file 协议。 +### Package Uri 示例: +```java +Uri packageUri = Uri.parse("package:com.hello.world"); +``` +### File Uri 示例: +```java +File apkFile = new File("/sdcard/test.apk"); +Uri packageUri = Uri.fromFile(apkFile); +``` + +## 两种Uri安装app有何区别? +**package协议** 安装app,只需要传入包名,不需要具体的APK路径,所以以这种协议安装的app,**相当于双开**。 + +app会随外部版本的升级而自动升级,随外部版本的卸载而自动卸载。`PackageSetting` 中的 `dynamic` 为 `true`。 + +**file协议** 则是内部安装,apk会被复制到容器内部,与外部版本完全独立. `PackageSetting` 中的 `dynamic` 为 `false`。 + +## 安装参数 VAppInstallerParams + +### 安装标志 installFlags + +FLAG | 说明 +--- | --- +FLAG_INSTALL_OVERRIDE_NO_CHECK | 允许覆盖安装 +FLAG_INSTALL_OVERRIDE_FORBIDDEN | 禁止覆盖安装 +FLAG_INSTALL_OVERRIDE_DONT_KILL_APP | 覆盖安装不kill已经启动的APP + +### 安装模式 mode + +FLAG | 说明 +--- | --- +MODE_FULL_INSTALL | 完整安装 +MODE_INHERIT_EXISTING | 已安装的的安装模式。预留 + +预留参数,暂时未使用。目前不管设置哪种都一样。 + +### cpuAbiOverride + +指定app的abi。特殊需求下,可以强制指定app在指定abi下运行。不指定的情况下默认根据`系统规则`来决定运行的abi。 + +可选参数: +* armeabi +* armeabi-v7a +* arm64-v8a + +### 双开app实例代码: +```java +VAppInstallerParams params = new VAppInstallerParams(VAppInstallerParams.FLAG_INSTALL_OVERRIDE_NO_CHECK); +VAppInstallerResult result = VirtualCore.get().installPackage(Uri.parse("package:com.tencent.mobileqq"), params); +if (result.status == VAppInstallerResult.STATUS_SUCCESS) { + Log.e("test", "install apk success."); +} +``` + +### 从sd卡安装apk实例代码: +```java +VAppInstallerParams params = new VAppInstallerParams(VAppInstallerParams.FLAG_INSTALL_OVERRIDE_NO_CHECK); +VAppInstallerResult result = VirtualCore.get().installPackage(Uri.fromFile(new File("/sdcard/test.apk")), params); +if (result.status == VAppInstallerResult.STATUS_SUCCESS) { + Log.e("test", "install apk success."); +} +``` + +### 安装Split apk +先安装base包,然后再安装所有split包即可。 +```java +File dir = new File("/sdcard/YouTube_XAPK_Unzip/"); +VAppInstallerParams params = new VAppInstallerParams(VAppInstallerParams.FLAG_INSTALL_OVERRIDE_NO_CHECK); +VAppInstallerResult result = VirtualCore.get().installPackage( + Uri.fromFile(new File(dir,"com.google.android.youtube.apk")), params); +for (File file : dir.listFiles()) { + String name = file.getName(); + if (name.startsWith("config.") && name.endsWith(".apk")) { + result = VirtualCore.get().installPackage( + Uri.fromFile(file), params); + } +} + +``` + + + + +## 3. 启动及管理Application ## +# 启动App + +```java +// class VActivityManager +public boolean launchApp(final int userId, String packageName) +```` +实例代码: +```java +VActivityManager.get().launchApp(0, "com.tencent.mobileqq"); +``` + +# 杀死App +```java +// class VActivityManager +public void killAppByPkg(String pkg, int userId) +public void killAllApps() +``` +实例代码: +```java +// 杀死userid为0的QQ程序进程 +VActivityManager.get().killAppByPkg("com.tencent.mobileqq", 0); + +``` + +```java +// 杀死所有App进程 +VActivityManager.get().killAllApps(); +``` + +# 卸载App +```java +// class VirtualCore +public boolean uninstallPackageAsUser(String pkgName, int userId) +public boolean uninstallPackage(String pkgName) +``` +实例代码: +```java +// 卸载userid为0的QQ程序 +VirtualCore.get().uninstallPackageAsUser("com.tencent.mobileqq", 0); +// 卸载所有user下安装的QQ程序 +VirtualCore.get().uninstallPackage("com.tencent.mobileqq"); +``` + +# 查询已安装的App +```java +// class VirtualCore +public List getInstalledApps(int flags) +``` + +## 4. Java Hook使用 ## +VirtualApp中实现了一套Xposed接口,用户只要会使用Xposed就可以做到原本需要系统内置Xposed才能做到的事情. +但是用户也需要明白,VA中Xposed的作用域是VA这个APP中的,不能越权控制系统或其他外部App. + + +VA中提供了一个App创建启动的回调接口`com.lody.virtual.client.core.AppCallback`,接口如下: +```java +public interface AppCallback { + void beforeStartApplication(String packageName, String processName, Context context); + + void beforeApplicationCreate(String packageName, String processName, Application application); + + void afterApplicationCreate(String packageName, String processName, Application application); +} +``` + +> 接口说明: + +名称 | 说明 +---- | --- +beforeStartApplication | APP启动之前,创建之后 +beforeApplicationCreate | APP被创建之前,Application已经准备完毕,Application.OnCreate未执行 +afterApplicationCreate | APP被创建之后,Application.OnCreate已被执行 + +
+ +>参数说明: + +名称 | 说明 +---- | --- +packageName | VAPP的包名 +processName | VAPP的进程名 +context | VAPP的Application context +application | VAPP的Application + +
+ +> 注: APP的创建指的是`Application`被创建. + +接口有了,接下来就是怎么使用了.查看[`VirualApp进程说明`](VirualApp进程说明.md),可以知道, +我们只需要在`VAPP进程`回调里(`onVirtualProcess`) 设置App回调 `AppCallback` 就可以达到目的. + +> 宿主Application代码,参考[io/busniess/va/App.java](https://github.com/asLody/VirtualApp-Priv/blob/v2.1/VirtualApp/app/src/main/java/io/busniess/va/App.java) + +```java +@Override + public void onCreate() { + super.onCreate(); + VirtualCore virtualCore = VirtualCore.get(); + virtualCore.initialize(new VirtualCore.VirtualInitializer() { + @Override + public void onVirtualProcess() { + // 设置VAPP启动回调 + virtualCore.setAppCallback(new MyComponentDelegate()); + } + }); + } +``` + +> [MyComponentDelegate](https://github.com/asLody/VirtualApp-Priv/blob/v2.1/VirtualApp/app/src/main/java/io/busniess/va/delegate/MyComponentDelegate.java)类代码 + +```java +public class MyComponentDelegate implements AppCallback { + + @Override + public void beforeStartApplication(String packageName, String processName, Context context) { + } + + @Override + public void beforeApplicationCreate(String packageName, String processName, Application application) { + + XposedHelpers.findAndHookMethod("android.app.ContextImpl", ClassLoader.getSystemClassLoader(), "getOpPackageName", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + VLog.printStackTrace("getOpPackageName"); + param.setResult(VirtualCore.get().getHostPkg()); + } + }); + } + + @Override + public void afterApplicationCreate(String packageName, String processName, Application application) { + } +} +``` + +上面示例中,已经添加了一个Xposed的使用案例.Xposed的入口是一个`IXposedHookLoadPackage`的实例,他提供了一个`void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam)`的接口,有一个`XC_LoadPackage.LoadPackageParam`的参数.这里我们虽然不能完全一一对用,但是也完全够用了.`loadPackageParam.classsload`可以用`context.getClassLoader()`或者`application.getClassLoader()`都是可以的.后续`XposedHelpers`,`XposedBridge`原来怎么用,这里也一样使用. + + + +## 5. Native Hook使用 ## +对于ARM 32和ARM 64的Hook,只需要引入头文件```CydiaSubstrate.h```即可,Hook API: +```MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result)``` +>参数说明: + +名称 | 说明 +---- | --- +symbol | 要Hook的地址 +replace | 你自定义的hook函数 +result | 被hook函数的备份 +
+参考```syscall_hook.cpp```代码 + +```cpp +auto is_accessible_str = "__dl__ZN19android_namespace_t13is_accessibleERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE"; +void *is_accessible_addr = getSym(linker_path, is_accessible_str); +if (is_accessible_addr) { + MSHookFunction(is_accessible_addr, (void *) new_is_accessible,(void **) &orig_is_accessible); +} +``` + +在`MSHookFunction`内部会自动判断当前是ARM32还是ARM64: + + +```cpp +_extern void MSHookFunction(void *symbol, void *replace, void **result) { + if (*result != nullptr) { + return; + } + // ALOGE("[MSHookFunction] symbol(%p) replace(%p) result(%p)", symbol, replace, *result); +#ifdef __aarch64__ + A64HookFunction(symbol, replace, result); +#else + SubstrateHookFunction(NULL, symbol, replace, result); +#endif +} +``` + + +
+
+ +[其他更多的开发指导请见VA私有库Wiki](https://github.com/asLody/VirtualApp-Priv/wiki) + +
+
+ diff --git a/doc/va_architecture.jpg b/doc/va_architecture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aa5d08b154dfc500e3ed5cfa88f1fa5ca50c1ec5 GIT binary patch literal 1301947 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�O)qWuH=_4DbE{c$J7BN?0-Na35u)2>io5~`9b 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 z O*`LF`bxo-9ALgPT_v)6+qLg8tVbFrQZM*d*kOlY|vO5i&}Da7C-aj2;BIs>75 zzbdJFO90t3ss?jC=N$)4#bBkXau(o{#mp@fiQL9D1?bWMjUt8dT8fSQ;eG6D40GggpoPSIV)@Mx;ZIs_PTCDHcZ4~z^Nug974|v} zU#eH!kA860IHEM?^xZcKW}4D`^L-+Bk1$FEHwNxvWzC{v#nT!NJg5iArfn_T`7OjY zosVm{)?3oEGjBc%)VWIuAb63X=3Ot`(*g$m2Dbbz8~OL}b;zB=4;l1$FiS5d;gUb3 z!ueZgoP}PEu*|!I>%$sGPCuRTeNfZkx83e!DjdrZe&Lh|vewHCg+7bcJ)T&5`Q;bT zfu!*h&0H(H^W=MUH{g%SE$U>isB+=LG5=LZ!wt^GwMjuc)9kI6_ca7xgIQUPozK2r z|Fo9c5+9>}k2mSP!PX+fu>Yg=NXSqFm*Igx##g3SkG)^cmcq$x2H3vc?J|2+t$}wW zoWY1FPh^rB1~tX_ydpO)EE!ElxjuOpbqwTtL6GUzCG|(E+nB`0M?;y_6aFfrQ!Rd3 z*zus^z(or$C{J2DV+Am0Z_)jHB?xJE`hI}wh<+(GC7JCFf)y_gM!bs(urm_!D&S4` z${gLwck~x7`m!|d6Uw{G+BLsDIqZMu<9f2|=A5K_svAo_Yr7M_Z=m`F4OimXB@ZJp z;0?41FG7I%~9f8^kUpvxj6%!l;u_rZz0SSSkAm3=uu;36WS$5Z9K3ZqpW1mfBh zifh~32WBbiC^fJ?U%%L#*X~m1go$t)9T%S%q%X&BdOy$aETY}Zf zXU;}V9=#b-7&yIemWcUMGOhD~{UtMYZVRHv5va7o(2Vr49_;obb;a&dw4EU4aag9qi_%23M(*!u?|S{FIaNx-P@s5k=S{J>g*@jk7vW3S*gt$t*^dud0V z^BL8_Yr!Xq7|lky2VTY3y9vC-tTEe56O~(s38()qN4dQ z@N#eC>+7_5j?pi=NIX;jMjFRxO@G41uNah>{TFBl`oi0FI?gHINC?syo%F&*-^2@)rvFW-V)qu7K~s3w58sqB&nYqWG{X-iTdV8-|?ya|z$?jY1+3en1UXM3`EyO73JQz(wc>!CP6-PtbB2 zcns+YCg+fgzN6$;tsfu#)35u{{qJ47_?uV~4jee-0cG>W{G1=4$G*@NelF}^Dd;`G ziN=~P2i*g#M?Be*fo;wVIo~&koa0WQU2jS>3!zJZQIlpGKu6QG*a_xcmVkk`-YBn2 z6qn!oICS~{#l0E;ZvNA~S^+@vfUUD7GZzs5DoK!^qogXCspe2{RRs#LnbHuh0B`V< za<1Tb{`3j|uGDr452a@Mbx~{U$Y~ve36#Pu%0$6e@YYKpm3z@eqfCC;ZTbV%2_{c6 zq3eOAf70Q%0)~hoI$;~|0)P)dme?~`3hQ<^#c%wXao^vjTR}P!%Yww)FHLPl?$X~| zb!a#v!`fzcLp~Fk=`yaAO!};jIxxodpZtEH1o2fFxx;eBf}%j{0i3*!e@_Fdj@byT`+r*4j=~6NBo6u-Gbi+( z{H_x@lIp$(WB}0VwC$PQF4`)=U$Ln<<&Oux-=&B@gW;pI7}DkKDNiJ z;F@qA`BH<<0p68D+_rrT_~74v@K+6Zbb^o%{XGr=0GXWtM`RuYq&r_5Fx14i@)%oW z4RiqN18<@qfz9dyb3lXEj*jIR`~R}|JF9l-L_09CKbS5k{b+>RRlch7mX3Y!19TWY z4%4)0*!;UPZvh*18z2lHETt9m0^Zp*eA~D^R-ma)7o8Pab8*tWo%^4>4U8%D(hty1 zDwsa(H$=TPCm-Rmha>gSm@A3G)JMP~5yb>dMU%$WPl-Qagq?2LZ>zF-&D->f` zvj_bL7I;6`!Cx2jTLeIlZG{5Omcw=yZ9-Q4!H=L#Av@N)kmz6vFt_d_az|^J6ILMj zoUlLb#{g3{LAH7>GVh3C=0_LLVwRb|qW0>0{qe}kSj7&L&i}mBAIAJY^6}qfo9p@C zWSi5G0ZTjb=%?VS3bV|Xhopov@FQJaLxPB7zs3?CBfp;V(_AqWouvcZoKTVYQ;sh?MV}b`Jj;_j4$n) z1@ALxzh)3=d7*IQCIjy5{IX}FM`qaR^!;9Cv8-l;7fhL_WKmCCJI$ICA{WT-5zQfwGN>%zhmmab-8jsCkQ< zP{|5mbHbIv#l&7pJNfx!nmebTz1TcndnGWoUglZUCC$uRvB5m-vu92+mfcg)FA~q% zvX0A8AL6%itmydYYZ<=w;EXlgJ;U@y)^d@iizh>F^c~hX4^LTredCkY#!os(NrgtG zmD!>M3vb>Md@6T$hRW)=)vcdmCsk$a zV?hQ1=6d7v4wb5q{3`oa&$d_U4+2(NGUO8EBmZdx{#W;p{O$CVmve?Mt~;WZJxiud zwhQWuZYR!Z6U0kCIb6w}y>?<^zK{3G;p1n9Uj^RG6De<%TrQlGV-E}nWb(=^k>$+V zTxd~X^1OKKI%O%Q{>$#c;T(sCo7OS{Pt-4+km_*nnzSXTl=W4$kDER#?M@Kbg?29*#7hRswdOwmj%% z<(@~G$PiJ_>Ra5x!3{g|I3YuMO>@WP7snd1eUIMlAIjGi6Iaj*t%t#nk;*sM&D50< zr`>L=ht8aeir}$)u@bRS@3y<|&(6d@_xHc;I`>05pj!?7m_?>J`kmxb#zB=ioL5Q+ zT`ugmB6U370NHvGNCO&~_l6gVrjtrzU3>jqG-Njikum!3-p3}o9YxX#D5vLjQ8h01 zBfVgzL{_@g4uXpGzt|y=|98LehhWqOq;0^^k-*R;N~&);2|vBDqaYzY&l+} z!A}0w-MjZPbh*Xl+d|cT8#)0P`fbGNFSi>5XQZMdm{eb^Jb(O`q3fG@lY$n*Xi8KC zc;3oAd*xFSpIUsSuYFg10=r#kE^@72@9EPNsnBKDM$_y3lqFb47usP(%5pP3#zuzm zNL;v`8<*UD5gWj8{GUw$vsb?q>HnjO^xl72x**aF@$D&A;S^K4S0>q6z;{W&Yq(J0 z$>H`B`bq97fi!`2gCfOhuY4m{^;tFV+0c3AX3;jfen%N~>*Bv2`(G#IuL<{Ssr|1FGL9J05)&uKPUElX8JJHl=aWqhpO(yh;|^ua>PS7z zes%w>Km2{mhqZ9_FR!9nM9wlp_~p*I!P(*=Koi;DB`BopT^+`@@zjRJ^MgW?90f0L z3CQ{s8LS1*y{TwF)nY2qBfX}gVejP?HH~6p;`0w`S1*qqZ~lD@U1a+$#110gr62*| z-;Q32Z0*KlsU@YJ@a34?bjOnUl&{UE#x7Z+Rfp88{3J;3(vTH{J1@(chwKeo zy3pXRfAHoeFVdz$F&Ny;fiFU2OR(*}=dfx%{65sLb9LwMufqx(kmi6{PB6ahEWZVQcQL@SBBFd8-rFlU>)dQYS0Y!We^2H(f%wK zyI4@N*>k9$O$0ue#!(0zN1M-q&^Z`6;&H34+&AA2p~sz zXpqS;;DdmXm41(^=Yio*q0+d?sc4ECY68e!j=M4vjXkL{{0lhLlS1IsfHFmZV)gyK zVDJ&BMR{OMBajSDnud==FcO)t?NF*(Gc^;wP`y~T08CUYcn#!7BT0r>@V>$I2Ib^8 z^s@6)eo6818H2!c#~vnc;c(xyKc}ZW+Dl0-vOH`#Ip3!5A4QjIlUY>unmMTDhw7SY zzwZcR2~~cP#&=zan8T~O#+-b69e;z8=?~i-;0}#2WoZizXoN2dNP2!ZMjFEEmffpjh(Kg#3KBd3I z;a&&-hkM@N40?VLv49BizYp13-i>9tF=4s&hWXZj3!B{!BLwc702ztg=&`5*i57Xm_lkg9;x@GHIk|A5l6 z9+uzklceHPwnbG+^1h#+_#+eFOQA0Db!4rzGh)B0oR+?>t=kuDl@zE}aX!P`eWmns z=gq2x%kNen!)#&Sv-dvGNPtEHG!p;c7zu%iJlvZfjKQ~;>P#;!<7SN$`Z?`7qnW}M zLj1ym^kNTu_8+Fd6S8UU+V>H_LNL|`##X_Y@PA(nzPL73`_h}sxk;MWR4$osm3$YK zpMVv_9jx(esi78m@Uj0>k?23CyYQn020?Lxo zfttijHg6Xn$PLfq{;kU)X&wKWyvhHZQUA?B*5H4CjRAk#3xG@aeY1n#w;E1kV;FLB z0jl8=Jm+(ea2xg$&?}0?lN7d!Zl#ni123|$+2SV&9wi#DemE)f^(Bhd`7@1(&<7?A zpL@x~FqlSAOkR*T92ai%zt5`Xa z28k3v%>o^(kn=Q%Y(6j?0X~5Ru3r0m8oPLa1}RuOcKYit9ij#pQPWWE9yp*On9T>& zqyW&Yf9;IqrCGul^*Zp^=gJgRHHD>`aurB8Qv84^ZbJn$NQV)%9ymzB1Hqo;8&Tciq*z6NJcd!a>|jiudEqOv}2}zhA+|}umua);#q3!5wqK*vqn-=U`xo{fd!>GNz_OKa`hn%(oIIS z=Ab&7N!IVN;7YAY47gIDOo7@5+9@g)wCJGk15pBq5yV+kNb z2BR)ud^h72-fkRgK%8Dz*HLk1Z#$dEyX3^HVpA%hGVWXK>x1{pHQkiq&X zu+j{yGy`k$!0JV?&J(PN1#5@FDr>OH`fFW2SY-`XS^o#Cthu}3V?7C0-7`(-91kOo zC7dUdB}ZFIQjd){<&fOh0~mp*TdT}T)6)rj=)(qF$8dOYV&qhu*+g=6x6h{8CP;-2 zdHb)9n*Valh}QL!BQD>~82x?6ZhpD)Kc7$oFZJVre{ijSJvi<+Mf4|vgrRkVA`G6Q z{BJ%*iJ`TCA`FV~f42y?f+7rx@PD@m|7?Ic2w*_~`)45PZ*~{>E7;$SNQ@tAv{vry zmcl>mkNv1qfot89vY@s~&`4*3_Joh%ar)`QaNyLwZ;_au{>7bD{M*J)t-k$G!pgmL z?~6$GX&myHslE*vN4Offhv+iaO?ttWxG=NN$IyvVtg|2?pmFIYx!335bz4O5J)Qum znF}vS!Z>Z@$iS#qf0+jrLAc6bor&Swd`d}1_@=SMfepxw8{Ru2xXGP_pr|56hk9vz zMRV$62Kx{!eV=W}@XbRtY2k^iQaCjaBPMFVI(7>N4ktj#_$}5 z-tQB~ruK2cDc{P-!ZKg#R!r^z@qNc?{6(P#Djw5_ee2DaX^@}xcn4J#RMo$MswU0O zrsO}+{TMN{<7Ar{TV3)~%KPjwOr01VK`AAN_)%R+{%*6CuZx=ULk2{nKQxgM20p>2Fwz5eWGnchN{ z4GVDy{D<;V0{`f3W)GwRhd@DOw6MlPig*-^@dG{9Dg`P>HKRf5>=IF}>6A+)TqGl? z6X#fEX*$(Mad%B9vS{MiyQll55<82<*2X3oLsmkmp%?QtBZwxA zY>xP6=>2}F5Jum;47dZ=3c3avi5{Am3!6f#lQN|#-I?{# z*7%4gLvy|rXW+zY;~i;w*PmnzZ^_-pI_@s5{Cp5|9d9zS6gm9RF3mf1RAs;X$dMPU zrY9jAE4pTL-@-GWo=Y>@3(KFlyW3oztOm%{>_GU?AWd*og=jP75cP$CX8Qrar8UqX zF(`c8IBWrMl&ZYGl~Lcd9RpJ(pe^|Cwgq6Smw1Nh>*=;g+4@8Hs>ZW0 zD)A)^a!;9vfjW|N^*AX6dm03SCg^iD7kyk=RM0ABxbx=xlQWMJ1tkSJ7YDOMn=re) z%}%5{JZqJEyZhe$6`zgaM;zyITJT?geC~H|lZNKV+?gI?#3?==wM$y>Pc1^|o@$!! z^DUqgzhLyy4Ka%T{fqSDE?o;?Xx3o6@sh>;iCvDDf`*LBNy)1y4X#E34Tfy$jfo!K z-WcN!&7C~zJ5*JkePYdewfqIAHt@Ue9ifYApl}VUmtMA#zWiE7^^}?!c_q7bUPEA% z|D2BV%{QeJ+@xM#(gj74w&HBY!-#-i%jA#u`=eC-utg?4mSmUI938Lc28ZhoN~^HI zSoV?T5v(Sf-qJ;3*UB_aQwFz6F}PjYa3xr5WiSW!Z+H0LZ4ozqIoi^#o+)zwsbf61 znMn6Gsc{!?!)b3~JCZ+B$wg59-AnX?7G}Ql8p~!pt+!LM?tIt9)a+v!Ot2I1Z0N11 z>@A%%$mzQ?`)3u;OmaVp;G#R3p?POl=MC2t!%XYnEnQi;*inyg8!p|a!bhLpNX~eY zDM)ogjIU%LATY=BiWeB@E`(F8WZaLW#hK}JdIxg7`?pr(XFF6lbB-#Z*2R0V_jI7~ zj--s8i~-vyPFaD4*;PqB@|k_vMXK|gk8G(t21&ilO19Bp{K0Pgu){wn;jgzSoaow6 zQfcg~;KvlQ|J-(WsSTOXo`-`u_k(t8Ee$}O(|`9O{a`88hb|I2y`%UZp^Xnu9aZZL zQQyuO2J7@Kyoz`*NrOa*I`}!Bh_;7TDL^+dsdGQ4H_wwG3#ga=0rAopAi%FY59e(= z6x?=NRsD*33`&w~!42W>?AI8PpnW=*bcI@atTOnTl3=cRRW;NI`RBD>dnp#hmT9p+ z$?AaInMW!ebl&eCQp*u?+MS zuML{SX{T|$wnsIvipi9PU47~MIo0>RFBi0TQ?V8s^+1;H9}=)^Ya%-J`jv=@oi%0$ zPG%kFQiP+SE|OgD#Brnb$~;jTl;bGf5ai`k=`0$>21CC2m_MudIjf4;AoXHDmC_yT z(b6Z)H%Sj&MCo&-j%YV@eX2u~oC`Mvx8nIit6NX8!e z1YS(EVdx-^Lnhz>S_NV*+s}~J(+MzdIVn=tyC->E+>B-z_!%5+w+h;fQXVsmRSPnp^SxOMUX|J(g%m0!a>ZJ;_! z2bZDyXir1Z6QK=B^GR?FRJF_A>8_Z(kXW&UujG-3kkYqOOqrXofn30Z*}npm3b6dn z5#0^>@-~K{$KJhG&VUFVD^rO>1Pcr@uzeiF2>!8k`eCEuO!Zyz2wPg(r&Ho@a_JOs z-M@f0BIRqC`R3^%3G_;>R>SRl$vS5r0tBvOZExCLGUHTOI~n zjIq>}<6Q4z$xdr-pC54hABe`u3Jc*4uK~BO{NXDUJM@JB?3MfsM+w>lV zgnOD$XUv}!GWD^GghuZuE36!#GqrCkzUmD0mQ(iTPVDKT8J1bSb*F#qd;juBbaKtV zD7=UeGyVKxCp*_h)l(XR14B6dAm4nHfOAQ6J?~!R(`UDKXtr(lX#A=$1Aq2eG*Ict z>dc;R3e&N!Fd|tn9l*Qf!qz}oaK;*8VcE6rT(3MsK26%>7vXDx5caMNo!zC>G;$-7!%1pi_mUw8JhEk5(oi+p< z|I#-&_SeiyAw`rbq4W)p?fQzxa4MuO%q}leQhZO@C9icS(_+6)TIBw;3}^$SMb{Z1 zEw=&E^6~y&$WAl83?(kK*k-k{L?}+*;xG7@^DX5BgV95n)+N=Z0vmp9s8k|R0H>Y6 z^;*cffmcknEOOoL``r7^z3}}pFrzyZ7V@B0zX$olPPe^eqeV^_L4_qapkk9tb_rJwNG?Z@&NYL%WmqJEctBOqIC2yNaFea?7p3F%GUZ z)*|b2LP8(iTR4fuz&VZa%d1GY|yn|z*xpQ7_(8A zECxu6j^rA*KdN#OqB|(ay3Sel{DrNLaCU8o=m$7U>>6kJbm`tEoi%cw-t?O3#rPH* z&6q#vdw=i=N_Y9i-#b5=T393aaSC1Q1m8x(#5Ye-m%yOZ`fTK@yFVfzbFu86L-wYD zDyYIAB76u-8szLkS+r3}AV6KtBp%-zZlp*RUt^Ta0HeH3E@(YYx-xnL=YAx8`Wwmr zYtLjtvM0O5e`EQqUs=9y(qgVY>-N?~0FFK0zD`~eC)eX)L4R5Z3hVoCmaN6Y-UIQl z(v2JtmbNt@Ch4#>wONYWx4ipL6BoNA=h3PLVPwi03LDh_io$#g#Sst82cmQw0v!3) z$>g35-|?28gg$;yq;=lXThCf_2MC6RZ#elRo5gy55F>}v!bX*UG#QC_%-^PYmX3R3 z3;b4iu9nkaj`g2?nrwJGW~gJvu!Fa1>!`{k%e|JBmN*1suKAa7ji5Dxe_4Gk4i-Sa zPFo)Sr2vm{fsOQ~Az zsGv12i6i4iKf-y6AmLx;$XbxKpgBG5C^k-^%z1|v=%c~j(>2V zo26gR2{=CV&_8kWMlF7vnz-vG-}G(DyTcux6+8POm@Ub+5mHjig8-& zR`uf`ebnE?qGr@Ku~64RSD&%I;gCrkppx?pt~8TPA3Mzn*_(hH<5e^9v3s zV~B|&Q)m#@spdEo-qJ<`w*DwVZ8S*#N9&bF82Pdx24kb?=V9eu#`t7lK8;p+(| zOqMvB205(Dzw+jJmM-xz@cSWj91?G1quD63RxI@lr$0qhrp^Oq>>V%z$!8Fw9yTpp zGl&WJmWZlgz}Hj7q^YNC$pV_KTG^v;II7x(Fa{&XUPpMZKTOI3cDdvu^{gBXviCst zR4-z1AQo*^H6lzl^DVdgwy={yoHR)F{(9=^XIv3fLsT{0*cdZ8?mB{?^sVOOCG{E& zQm%=bk46oOWOs6`?!=2^58eLuAQ#ENAg90<8pQt$5S3Wa;35V!56t(M6RUwCPu)<1 z^{vmK@Ka`hgoA%84f6I87ik&lR608LF^{MSjMy^79R9Ytq?B43WF7}x(4QMfW`JVy ze&3~)rz+|~4tw}6wO=1y5zcq;s zT1*B$;*S8*J73>b=CLL!!pQk3)LU7u#e+0R8ER2^5{Eqe?Npu%Y$S;6fF1K+Q{#QU zl?H?XK#k#D$}0~BbL7@V@^l-jf9ij8 zic`ZhAXh&1qH>wZR}C>ho^Jg;6(8|v%4Z-MKQyQI~a5?|`{&gVIoUXW#N`1nbp$ z*rGAT!nfS@7bQZUL{;yvUelp)4`5bWHQf-!6gy}Hb?g4cx(%#Zx1HVOTd?^(z7?{l z*#XKmQod&Ofp6OGO*8^535GbdW?3!`VxruZ*DcFp81=~W>^Q*&|U76EI<)G)c;IsnQ z_B+b}$X`};4a~>DSAua!eM1Zr`6CryP0>c_3}V=R(dqO$*gP)(t4brIu=B5<(;zzh zD^WP4(7Kf>gSwUiCbtSm6dv>@Uoym~qE}045OpBgIsfjPTqRL~hpe`sI;|T!k?c{J z1n}C0K)DIrKOfgyo3%Z^wv&@G`<;;?K%LS@2bLq?ll7!-sMFH7YjsMh00xUUh-`2j z!9@m~P~gsLQY-51J1!t;`L)Wv4|@tQ;fF9Q4e&vBsEa=h(uXCbFB)P31-=OvBfgp{ zh9taG{_I=%7>7JfoTG|$qo+8@7i=`x*S9>%3_fRHO1>3D^Wt&jG3dtb+!! z>v?wdH!EJ5iT4KF5o*mHX^!#(?g-xHM?E2+31pww-=aSQc!4i{sCPik-kt;59VXNn z8l)3QaJkuhldN%61bn`S21!`Aze-$0?`9NWe`yeH_#lIC{^7MPSFe%>Tx0GpuCW}a ze~MU283`g4P>XT;65p=0sQd&zj9gK`tM(7yym7x_r;tQ`P4FUoFE#qiB4mL!wQ6Erh<5}=BEqbrP zWT(NP*TfaIM^(BVY6SaKv5%^iLPkB~n){;v7_bPcRCqVk@n2kCwS-N#UGRlRvBB*S zg^TBTEu_0Ex#9;iw~U1^~ z1?LfWZk1>ZKd+j6LR?f=+Jgki16hZDy1R&ZqL|F%2(9U%T~BvAz7LF_*HG|H)roj) zl*1(Ygh3#%+*#9naRQH1YyKTO^4(46JnHJ<776X@ym;w>Z%X2UtoRv!7Jpt7w+EMX z;+`xB3c&)oLjJ{C{fjM9T$nl5d|AU!(aS(i=tgnxVCH=&6L5Y;;E(OZA%l^MvkH+@ z8vARRir7QDiX>bIGyA!M^_`JdI!;*B*Q*k@{{RtY(h zoH0(vmF{Xpm%^Yua3pkp`f-V!JLQIapCW&UFn_1w*WAS}7q&r@+YPi-8?|^HMY3+l z$S__-`2VqukbUoLeYI_b)ag|q!@G63IG0g>CCkzGDRY8mTk*CSJie17dZISK-1OAY zXWyjnwcuauED{!0q!n!(*mQdG0=>J>!~par0F*LKBSc?IXG#?wn5qtU!04lS5InzQ zJHGpl8cWOM!pFRp>KvC(W{Ga_&FlxwA!rW&jk5#I;s1s?RBlbOUpI$4(toAQFJwCs zwf*gf>dG`R$`M=f6CsA9a*ISxcM{o zP`4Xv2(J zl>Ni01pZE+0xlxBh@d3?A&LRO8&I7=n+Q4kSD8OS=-{Q>Qg24Z6eW1Wb4&TDz-%?}$>-~EE zO0OUAvtM%&|9(?2U?T(23jbZKuv=L+5!*!ajxJ{8B`OV}lQ_JNEzIEdT!xv;K&N`U zp)#l%eHsLwVVE;e10QN`D&rY|_F?4#6sfYWeiX7uXCnzE+*vW>A33}_WqGs?^kC*y@Y8XLi zW}sn@yoKdn{>()tgqcXdxHG$Ydj=yCvWu%3&Rag-@6c9RVe7}*%V!v^IUNc)dT)BG zgt&!oezOSGzpUfxrHAydlX|@k+nY z7|&L}T6HVsHz5h=I^7Z9LML)Je{6ZK4aQkX+S()k{Pv4w9QkCKtv4A;0mU9WFO zVOmZZRc4>uZHA1R#|g#1PS$?|nY%c!6>?uy6{odxc{W>&+|oVgRxv^pvfOKZ<&*qw z?Ty*fjg<{sdtD7NVr`3<21Zfs6NMumEN6Jxr93;;$L@@uoaXZ1q6HgPZ7;S_=O1lr ziorzeCwlfi+Nhx_g^Y9aVfC`nOz|-AxRD-iq{l6f%$bT5)G|=5590Ma%?1oxMVYP| zW-ftZJcQKZau8*ZV9FD^49F-dxr)fgL(&S@Um zXg-{9&k(Z>KS@V!?Kt={t4^-@LC}zIrB9`+(@a{J%I8HyKtq4x7AJ_aEqyWfb;KtP zc+_&FesSbTP$VKJg4Oqgx|nsN&ekNg@@$2VU?@)vGcdISJQn&|idXng>oRDKIX(5d zRu*nzb{*A#5a;8O zZ{xZcl_k9Am7*D5(|}qHHD+@r@Kl=Mo4lWDm2x*)4r-?R-=rr=Tyd|4-bBVm_@y}W z-pyw5Ic8ycj(TYV352lXi5s`(l1o$NtRT`R3^Ay)8MkPVN1RXtRKgt@{)npu_nX9g z{BJI9?qG4>JecFy6k01hlIkDU@#0b4)8+RnKsU>FEN?JpgkZ6rcV`EMBNQms!Sm*bpBya(^2m_hERB9PNT7mBQvZa7cNe<`F4Ov<9l-AEi>CV&|D~`a`3+ zT#9ybm2JE=+EzzGb|=L7^i*~NO^jXe%A;pIu77}WI~OXy^fkTdpb@Y?=Ro%zoCQ{P z^Mg|aoC-3UWwdlGK%n@f;Kc1B22Sns%7t~)PIT!H@a*RID|CuBXr}k+9UmLXh+(hU zd1`k8cJC1l@&z1%2I0Vt?DwRe1#0g1;p(5;0982-vB2>^MXnoYkhrz7 zO)H?@TVNYdxCxwhU5d={&?82m&X4cUbxj@EYjrH}X{Mb9-Mx@`w<{g&9-MvZ#sgzd zbmHim>s;)6d!G7T(v;!Kamd}BZ@#bXLFM~w336$xkUP8L8Rx7?3%}Jzi`x~s3@1cUDkOtmbRBBv|1WJj~my?w-GV z?Tp(llyOI=a?KuW3D=iqULuJG!M6>N`Nv!tJa?8sA2{7RlF4z80jj}jDt)&n)-X%7 zKPj7PcU{*^M<}k#Wrvze==H0T-Bz-(d$*WoDUCjDPtF-5JZKYR9Fa6?2P*?k#wu zVh5V;klVPcVU8o-yD12xRT{adCYzZaxC1sLexqfd-eme`>%?W8K5o4T7ieb<4o~=2 zvbi9Y6js z?05<+ga%o3te`=j+c%S2W1AOFWmADebXQr*oyw@b0z?=MqUk!Y>J4C}#sf4+k|L5I zN4ild4jg!uIY15q&a_p`QL3JyM*UGOX&7P(hDE=U3RI4nU9XP}`2VmDbQ)pre?3b@(uJ-$<8ww&Zbmrqz_~=0I2$-o9miaE^4cdKg8~n?udA+5w+1qIwCT8etO;R^}ZkOh$M( z_1Q9ZdDjcz{Q^K+^%(4E(86ms@EO5<1Z5S}$6pyi(B^=474#jTe*|$3h~+@M3Sx4Q zcYxdqV^WRN3+92w-uAV&r{ zGRToZjtti4fHg?p*I8ALXzWVrPJ$k6Eam&3gX_Pl3J1#NJAYEBi9CjCasm!{Jtm;Y zhWRu|#>!dO>F$+bN%*XShV|1*R{X7a(|%-IbfQm~fw}xi>|E+nbAp&FBG}^W26oCY z2|dOf8QoieY>hzSn;FS|$cY$q;|TR`rLkApf-#z0SVe;z>n0fy%dt(74Y}aoz%>Bn z0MrH09)LCx^b4SG1n~igkw8ocVnPrTf|wA*gdipaF(HTvK}-l@LJ$*zm=MH-ASMJc zA&3e8uQ6dI&_*FHuAtPjc5m%wffRSE0ecn3Yo8P1X^@S)m&SS$uUsN=HY9u+o>0zQ zow1~Jpe8YsO$`JW``g=pvoHQnyGj2n3&({=l2dw=$***Pq3@~9abhU4oiO<<=V~&( zebjwAR*2_s(NqI$*7G-P*7JY0DNQs8;Rzh?3G~<#048eBvnQm`AV5RCm9C&g&SiRb z`9-)ZFZN{+1wqm7WwTbvz5kms3*@Z3|6)Rx~a2l!3f1ok8PO)>mWuhsvawzPoS z@^v!(|6xNe#k(hSo(Ub&5-M?;=7`?w=p8#(qDLY}jtX$Y@eP}@G}mxX$pom7O`fW%o?-g_kh+$o!G zr_Y0!$v$Lk8EYgC4Dbk`le8KQ5&}#~=;W!TL8N++W6EQ&l?YVr zojJJ4q~nk8LA9KVB(@W)smD>FpZh(UI|$Z|*0u5bYF_T?z8gKq@qAx3^TGaeIzko& z@6yVgMuU17Z{1n)U}QcRa*l3TgF5cbteq5iV4i{O20LrAW3um$V}b-{qpN;8U3X_# z#tW((9k-M{IdWQ?WBX-}JvyvejP++04$!%^RP(7lF|>%^OV==}?5u0c>?#g4Lns-=dZjjtZ#GroYxa*QVWgJhkpg4ChUI3F%WwunWz{ zYBy~(boP|{M0l&3oD`zjjU@O}wLh~i$IfcR`4rtlZ;%b9aQa~Kn`M^{Nnh0Qq^K^} zFStJ&DwwxJzy1V|P5{~fGCK#ZYRZmSPr7ITG`BlfV# z0Pkiru6wdzrI2$NuvzTlxl|6qrF~7s#qHHy!>F8|I7!VKJQ>ouxb6 zhbC4XSI&(KIE5`+k<8}^J9z;lo`?^EFK85=mRx0sq)gHvZ|-5wHBE8e_F3|I?Ruw` z`eKo>z#G@2a83KUcxAseng$s=>Xu2`*RV;iR7cm`Y?5W?!&<4K2`204^VO@yA83%s z4yTkSKwEziI|}`vo}-z;Cp0sv{|nDBt1B?n4^vs*N`r(JQv3F!=eH8NivcDO3H09{ zTBc8`r&JSD79_VcA9WrBc3Rszoa~8lZafiLuYuOqwaq@dXsC2NTe+lO-#hJg5o-uq ze_ItB*VyyJlwo1R_GbPz-cV;byj_Ebjl304if?~Er)h<5Bv;P3>1(G)CmyNZnOy2JBh%JU1WV5jz>rZ2_$I9SOuym#$)9Hl{yOzF#pA0=$TZVp?05&S4% zqJxgL`hL<J5Pz4M8)cb2>hNbyWg!<+Ao8d_Cu-n7Jd?vayMe05lDVZxnu zy+hJi!p^pdnB(PC`-p|Dejo64v1H8(^ zH7d1-QCpAfWhn6Mu+$ml^S%(N%eUiVqn_3wx61~8Oa(E%%>vFAYWUR8ZQ`#tl$LGB zRE1*S^zBp$_8_zL?NU5U7EcZm&GVSrTJNjXD1U5Y*^ak28p`X5?xTz+b*tP*#n>%3 z&%8NzMz+&j<01Rro#JM(5{^cbf~tEP*>*b|@?74B+&}%&Y>@frRbin3o*_kYDS<6F zRXFB0&x;B3(DQMPdv^(FMyH5aX1F?hJoj8|pK2^~&;gRLu+1Sk^jY^qL#c5oZ|Mf; z4q03C_CB^W58!CJn0$n%L0JmY8`pJ_?p88S!u>>s_Y#=PYt8ftR++mK?v@l}Z02o9 z55W|fFA!NwRMVD(HKVlm1T6;AAk&vByCqp;L-nfqBb>wVVvQcUkLTF>_<4t*jzzW$ zOjB>YQ1Q%P>VzumCW}&hAKshVhq~3adce5lW;GUWS7R4<=fnTGB{8rdy53+Cw6XEI*i1hw>S|9;S9$_RWwxb&Ku;j~Q88pZ%6jdmN zB2Rf;)8?++UvE7NtR(`a;Yc6b!F}U587KCqo!vo%_n$y`Bw?yeRU<4#D3e@#r^8z{ z=*bNl1e?4$sKVL(h>69t6825QorG(LP&)7&_q-~cwj_rrjz;a{W(>a`lp}MNCZKS(@XjFqHV?kl3mg1k2dA*F=R3!u=J|J7HqBE9L##s zX)czW={TILgyf$LVv5|ubyo1WuWHBXB;#u>D<(ocdT0r{YrZ%4a));flJ0%J^~Ofw zVP!1fgMj&=&O$*e^}rmOJ#MoVo}@FbLnOU)V_W#R6jtJ{JSvOeP zU6w?}h}>N@WRGsuI;AfY6$YQr=T(}~T_G&@3rNadI(W6sZVQbZ8 zL;1r*pZj^xfw^H(t7&`Dc?g{-Jn3`909w-iflP$ng%hfsZ2h~_$6hm0s?UqK>g7Hz zJniOhM1sIA?ukjCoLZvqJjc=ji%Gcjq5^wgHN7aIr8 zr!L$1-)C(LQeE0TlOmAuR(_VhxePUDM1yFf^qr>9d&e=h%}JP(P~k;mguu+LF?tfZ zlanr_&{hcB<^|3Ie6#J0rIN%6c*9j~@AkQf0nZlQj>!`OfoI#phFsCa8kmTp<6@1~ z(MP)w`=>TCrQhdaph2okVw69!-b{bHbrZ4tSml6b&jh3C@QJz4%Fph8xZB*w$o*kb zXYr*_?whB0S>-nc7ip0F6tmjPlH95T63mukql>-!QFQK>n7Lkh zplTgGlR5bk|?Uv{+OljV=Em&;8a6F>Nde}PbQGSL@vs%2-*$svDV!k;S%DA>uHpGMrHeYG0 zf)$eBdku%pS4Y_EgnQu^#QVAgSWk$F(;&)rV-?Z_8l*`$EY?pUBlj4msnLUTD%?ZI z3Sn50>HhZ?oZS8oaKrWjU{d!7V{#Uo%X0 zi=ye9#F_4l)U&zMy9QXZcJ272=f)vAGqBPV|0qn8==YFFncL=SM7%)s+WY9(yF*@F zZx@T>R5}t;)kCNSV<&8YBYzI}sHX7g%>q)hsP#o*yGi{(YzIrhxBEO zz{IE{Zt*5b<897BkYPJ#^i9)Y8%k%n{f??v`E=<-sd*vq0@m1_lKZl18~XN<1r9e? zqaKKfK_0qEQ|^yR0@f+cr`vkAPdu&G=!XBL+eY%o?}(M2uH){yXE|sm-=qIwtoF=l z7xwlWH{F+wJ|meA37cJ!Yt1u8M!?aL-8~OQ>Ek8N?;Yt9dDeO9_Op+WPpVE~y&IGk zS9aO=qf5&rm;=Q2#H zr=dGekw5K~^9>s~O(~p?nixI%N+l$7R~*pWevDzoZ?d~b$7a(zQNnV;91%CS9HvEs z_?G}&pSdw84<)PYhEj0+-!QPFUHzy|@zqf*uktgdF$-6--3#45hE`0G?D@y;wOe~9 zHgbp=@taQO#T8FHksatdwAwVl$z*;!mc!}gp5+Q_s;$*FzDHh`w*xrZpF zC9w~m%RJ8-^g*PInR(P+2uJu#^_dHq!jIf+R!$F$5w{y#_ULY;L85>kAT|=ENrPxT z&(U$aOTS1{?I)W2dK8*R24JqDBl2;!>$AM2~LBsv{Ii^KMk8nrq3CdF00ZYS=ekb&&Ek; z9ybtv`lnJvH6SMc=T+1D%hDKa+LP16N-4>|X(o}A$>rA3<^6u)yhp4mujJ+7 zAdz6X*H2E|xWEcCraGCmIM>&9Ro-cr@NevfOB_*)4sIE=XT(NvHHGaD<)i0&!EEcR>te zqxpUDq)GTLq@`QDgD3OjU}vj3zO)r`|8ZHldr~^L#M; zb+P6Tq=d5Jfs;B!PDK{FSV2Nhb{VGYpmt=!h#XY)O2@*a(p~rH5BV)dUlQf_D`y2s z#%?H#_S}kN+p|=;iQJCItiT&0W3DT_>-^YV`eos1?*?jS77dc$d}M~&Ob$#_IUJM) z?}TSZz8>dHi24amKm(g}ikL27$O+90+PO4{It^mPxDu&K zPKv}%!!if(72@-N(^Muo04^j8cz<%EH7R}d0O~CU{|JEZc^>KLDXKw-c&iJksZ1E- zd<0?gDN`lc^Csjj+rhLhi!Chk_H*% z2dcNed8U%-XL6s2Si&xi$VSn2$zgM0g$14*`cG#c&qV8I^DmApM`~vZhw2lS^IgTx zFK!#k%MVC>9^EC?^|Yu3PI-viqwi3 zE|_lM65kP^iex#p>FpRQX^90l77rV(rk-3}aZ@P4eLywCPuzr`!19rS={c+)@8Rfi ziyu4vW>_D8G9oe##ljcPejp*|lu6ECD7`=&KeQ@na#eXrf?Fo?LRft%d+o73X&iPL z3rt>PZzCqRC{gU3QzJH|M~-AaO05s?n$$FE5(w`98p?m}rDob3O2r6{GzXqJx#DQcdj!gIeQIEy8^eg;eU$CzQe`GF}tyjsybAWt7=sYA$9fOoHJ(pEC;Zgl;pd zoGX>E)DbqD`&K9cKFiefZ9?j@m@9(5yX^YXH%PVwOW1B$@@5n%f9qWNfzTg0;;z%f zU=5eIipW0dB!jCh-SR5!t*H7vcS47&E?uOcROjw3?*}940QzjTth)8G#+8*AXYUnm zyeEYM(8gW_FafE=6dStAUJ1h&(IB|zm2~KOitvom-JRU{s=DROoN>*V+sq-4w$mU_ zi7Ka)KBOL*cJ;4qomf39FA&C*$RWBC**tLU;LxKTw+3Zs5Z$HneN%5OsZcmM z2VGY{gY+YHb?3P_OLG>TEocMAKdZ&s1HVz8}82xC{)JNlB4^8b?kduZ7yUj zsz0-{9I2_1enDAH`T3Sr0%BS=PWo+!LhxbuT}U-F;Wm7bvOR1 zEopepMI|BI1`+Jeq`ENbSRgvr825gRe5nbGDZ)xyn~cnh+@HcW4iAL)Uk)LY1ubwq zF_-Z5r`Rc9I;0n{`|wSUd9EkpQQrLcn_*P5k2C3v@}A2@E*@UW#2WY+j~IeL+h_CF zY447*v8A{vp?0TJu1A)L&cUv|IxnU9b`~YI!f!e<6z?c8rG26rA0nAu%6qH}*a$zw zc?vnuz6aB{bonz4axG|;3tL`xa3=jDG3m=AXYS@_a;ER)4<3E;VC&@8H#@DM%bH_V z?$$LE_BKV2EVNH4_uQ~p*_VKsF&k=m%;vZcm_C(M$-OL~`~&htebaAc0C~~_A{b>` zRB6@~z09uq5}9Ot1HK_n`F7o+HVVUE{<2ZNJaiddpBD9pOi-V%R`*jF3C5$36FKy)2?8<{HV!RTFD=2M44K)PcMoFQDz?~tD3jycd78z) zbNr>G?KA1}?t!-cFu@eY>o3K<2_Nh5&h-~c2)FK^RffhKqzD?ST|T_=rfPd=0Hv!E zVj?_q>)uqJoFu#9v2j}g_*?Pn-p>w?`1fzLnOK%Q+RSrT39RG#jiR3a9az`_mQDQz zT>k68?`H^qDRTHkK4XkqzWZ>1>I=$saX0zikG-4PDtFe8s3xGN1D{$5wzVs#1`&>v z0w{rm!m&ZASJVwx;U~*0u@U|Ho#fZg0{8K>lOE1!%`hC7a#M&{tItpLboow@OxU|VaWbf>4013^W30VTnPjj>oG zfpxcE%c*VI!g!%V z^8c~--ce1i+tzp#6;uRK5s?xV1QiA8QUjtC5h*H2R{;TO0#ZVIMHCQ((4>=qND~2R zA~h2~2_xxMS9=Ii%!)R92O{JGvtsD9VXJb|eXIJG1PL!Prm%Q5Q1K}bb`yHV{ zqTu_=-JIV=rqWnQA~9K{plH<~xOV;-!KlZXsq(Lok~5wmN7jaG72=A#WsR;u-->+x zq+Kg`sHjfA;0P8KD-O@hHhiF$qnaQbMYdSBuw4{wiJe!VHhq*)SoE=jWsRl-$L{_DUM7pVV3gvmg2SDlK!z;3=yY^S%Cso*|0QWp(vVIkSOI zoOzd)*Lz;(?;2%QK)Zz9{M?+PZpFDqv7_0&Yy7(Wyz2-3Ub*INa2ZyuXl74BU)Hox z`L;|%O9v)&l-($f!{DUS7gp@aJ4&#-N0WHmS*OF>V-<_|y|>=&LOi*O z8cAE~%P=@i`v5g!0H#c-!9;%YNX~$c6D%*lxC zCtOPRd|te2Pg;g*V530bQ$la!+5BJnse4Mh@JFOIEf2Sr*Or~aZ=@|ub56B}-R zB1mBg*tEtszN3ow?VM>Wsf7Ki-nz>g3Dq9DjhoF?L>jR_uqnRXnqK03 znQQA|{C(Q}l!3Cdh0LPAWSVflU?sHhfl{#tx4gS|A%Bg;S`_{eSsu9?@U8d^fLq`x z8tdpCTQi`U(9ZV_)&N3cGhiw7ORujB2*Spcb|EpSTf2~NA5c`Ji8qvL$FV*^pAkmQ zBdUCtLEV*jDSlh_%D~f2Rn&Q2_pve5JrN)DSfye=9*UR&m4J46`jcbSfG-Nl(;Ih* zvz};Uk)87sA9lEgVI+?8-RlW_Mh1ypJgyC zs(@ip0!QWmsq7OnbFdX~&utiJc+&%3xJaPxZx#*jfUCQv!e?-e|x_E1-Ps8b)IB5-%E?7O72lzjG6XL?Dg4r1Pw>mRn z@jv;a=T1*GbywNd9jmnV9UAMMU6a)fVT(J?=*8Xuv{#^oO?kfYycAV=!vJIvC@vaj z^=&OLro7`venMv5xS%0rdS?V|$Xk#7Kv_*4fjf#^g@5bcw#9a0M`KWqk zhRwZUDKB0WcH~44v&@v3r>B*Y?yPr{lQD^~IDtKWeIi~yn?!Sp9=Y_Ck3U1}@F{-x z?3^qd(#t31=E#w4S3~M-mn8He=*Ju{tLDJzz8*;8_e0(2Qk&9m0+ zcTl-1?cq9d?ghiasGC2IA7)P*dqX9s3=lcV+Whc4dJ#1*HRQeP;x0VrlUCpA@tvN~%Z; zy_{#v&*72Wy@GH$Yupm=sPLF33-I7XG)FcBxGP=TwEwp4fGgT(obXiOu4926(V&#l zlOyS^_=Y+{o#?9C`PlezX2ncR)|4NgrQYZHSvK-vWSHOiVL7Nxbw(}rhN}EirB#OS z>|goP6qYcCdEqvlH9&YlQt>-CM21fmrTOEG*&W_Hm9JL|Y6?79CDdC@GU1#aVuw#*vk$~ zS+BWq2tn8V+~IXM)vQdj(&>5Xub6x{#nugiaI3h?0R+1N6OTw$_@$a7{pX1>Vb^+>EF*_=Ea=`W0jV8Q9Z17zYjMk@i`^}%s+e;m zk%W%u^a=5Au7}^_ zHotO$#xhJEEMhglima!un|E|vrabE%qzLzpu$gO}51Q*_P%h8b---5e_Xy5kbsIM_0K$Ks1mjYk;5TSh3R?y)&SFQn0V<48-5RK+v4GuRU}K zIaWUu8Q;Y38JvGy)*KFYu!I_LLsrdb9T&)oS*J_C%*nQ8TLmsHdB0(SJT6jyw13}) z61h$k(zSv*rD!{ixO_*Cqy3$r$I+`>)9P~?937g&A zfs7lKz~wyK6xNc_%FvR!L!#$vJ?a>ZmITXN2cD-RzdP9xR)sWkzF3EEw6(han&)?{ zWVez$;1ljLNaA)m@$TcX00Q@Mn?c{(`E+-@EC- zM1#^pb@?6@=;tr7i?Fvyu}MCc12*bz9Or3CawdseRzb}E=pa}U{{AA;Z|?6;=lmIn z`%fb5|EjO?x1kUF_vpj_5&H0-?|u8P2+{w&e^L8hNB`f$8u8EjLhPN!|09$A?QY9n zNB^HWx&9wVzxQ7L(;d#=?za2`yQ)8*-q^rtz1F1NeDE5}F2Wym{oz9%4Z+8UOtX4A zbVU(o#A3oA2cxu=7{yYJK~MXKoM{}`povEw6E50a92J{UK&u%2V$*zs+BL z0I_{+5k^r3jSE-s+i}0*oIR*{+8_baw+p!o8dkoe315ItC)-^}iDk37-%W?%UH=60i`ve`_1Tepa(W9EJDeJ{>4`ic`H1* zOff=gfvO`tVHcv|477m?X6jfE$i~~_NcrYDK9@Z>fRiFyyP>;bnu0J{g|_X?W5!fvm?-7EC>2#?>nr#<554-Rhc9QMv(j}YA>hW7~a zJ)vMvFxeB1_5`#&A#qPo-4mAg1ol0n!Jgq_&v>$Dz}Yh*?HRH_=h~hz?GFdv-Z|`@ z!(Tc&{|DZOL2!hh?V#OX_&qB@zbEXS2qfq!v+Coo#d0ZE-2(Ks3gIORi|CF08qI9$R3y zqoP&NhTyer5KVpsSvW|tN|JvQd@u&Y^WR8~G^52`$T(0YvkO^s#sYI>N-6!R?-J+} za=;_DOTj5GKXxIGu$d{)zS>75o40CL<4Ac`pj}nJ64-(+HqyA=QQK8?JIcGwO8UdH zSlHYEXuD#decy$ohl3Kc0jdoURon#r@|QvX?N=2L1jm*s`eUHKHW%D4z`8L-50}%X znE{g2x}8zb@H>owuG@jrcKqohKvyH^@y+cZpyN^AXuL7pf}RJq@~*&!5!*KwVe4?} z0Quyy2Q}B}D$tjYqciS+N2SJ-MK6FQ?)^o3&j={nd+YwW?okv)MdfQJO!8%t>Dke1 z6TVU&R_}FAe|n96!Pz(GZLEtmYqv&zd}jG9_`s&uF`s6a1FeNg%f7it{>eYafqw z3Mw#Sm+dN5G_jn8Pup%Zh@XSF?~AqXK5_1}@m~ieBJAIz(!gH)`z?9wMfANKwU>4G zkkS7ImU~(EpDXL`;qko+W3Oh~t84$D1@@x%Ui98$Q}!6IJq~Y=mE7Z5_qgyqc7Lxv z+N+QD>Z85-XsKiKi=a2M-Xt)C8n$@99XRwDKhQZMZ)XAz*5dJ(5o?p zb#St=tGY_Dy0N0(CHE+cPcv5U!wK5q4v6y~!|?t#bAJDk+hhML_e+&DiA>kc6QVz{ zpc#JK=%GuH!M*7hH@|kQqrAo1t#bbMqhufPBETh2c52{m7I2>tSz6(wHn^p*9oX^# zW{2YtJL$_b?XTiZSf1Zkg8Tp^VfbSMyO6~M4{*~;lB~7`Fr^I+m}6w5bsXTG0jckSBUMs!|lOS-mNIyqcZhAt-`J~g=B?l4dqQmsNllj01h*vg6?pK^syC$P7QWh&w9cZ!{dU(4kA zD7D2s+b~%tiTdwRnN9L*TQEsnv0`8|cGR9Z zi0QGxC!ah!Ts>#LCcq0CoMUNRbhQznk9lYpl6FjuoJNkLYDQ9{qpN(;Ik^Au8K5&T zozh9c&@Tc}E*^-ob$MbtlpJp6MY5_&{IG-+UigS_x4V4cr&2-PecSz=`c;=0v6*)3 zejRf!Yl9np%=6IO0Si^rLwBDxpNkk0E%6K>>DsNGF0gKqahplY-7tWPL>BHQ~RFHWSgGVA(QsPG^BVJ zf^ouxX_D3S6^%&LZ!4o$S)E&EQ|^ZxXZp;SNL4B8Nf<>9kq5ME{ULqJZX5eYvwpa0 zzVXf7g@9{9uerfmsvpXi5jY((%cDkxRg8*@oZYP;aknHtBgeQV7J1u|fj%eCB~}-7 zRIyCYNf7r#%4&>z&q|kn{T_?e4~}}9 z{`6DMxf55UvY}Uh^gg~J@I=^||18O-nPLA^FaC1PKjxYK$=c?Bt-N0akZb9>Kfzt} zFLoi^Yv`?0Ktmig8a3lm0+|2Y6!4tV{5{K?%YhrrbifvbW75=mu*sk<+zUZv+=WaT z!Fo|6++l*fw1sc2E(kyOKzB$No-KJEn`r})7g68q7E-yWO4E@P|=_Y;_#>Vgs9I5F8 zQ89k=ad=I(Z}jly^ET}x))|^52i*9yaa>zCk%)^k;V;BI{q(6|G*1pA32t$;mlX~R z9)s!bLhgObQo1OZh+q+Ofw-H=5RsiWXrXM$7PGWf;>K|5z{E-s?^NY4arKFse(--^ z+J%HKmF_~W>jKTK3kuO}C2Hc+#1=#WLlQRoph`a%;zS4bYQ< zqUpA2Z}Wrm_F=U5!2M8adK`KInzM|KG$%(_;Nm5R%>^i1^)JfWW{pQb*`54S=X1XA z(kGcgU1er9-5&TLvfC09@w82K<4`s(#i24OeUbB?iTHe97#IVdQuYt1_S*ZbXEYT0 zMTs24W~bUl95R%bk&WV_>3HxbH*S=vaJz7(mz{1LlcfSG=Fi93E?5*u0U+T5k}lj1 zuJor9AQ@vVUL8(f@>|`M-calIUFM=TfoBv<{n;r$kY|&4uW;7T=sCxA6=>fzk~EB>!#(b{||-kcOnTf{tz?O$K~m zecZLXkXwmp;x42RG54IVi@|NM_HGx@opE#*L0#(4UQ{#krFwX3m;ARfQ4!YrfeYd3 zjt_G8mz+AlW>yV*>`pCpT`B78do5KlV;UP|=7QvOouQ!VE=f(NYc$9?Ljd zN-ikh)=+VdxHNmyW~@Fq6=JQhC>1Dczsd9F?SS+AHeHy}_VF2_MdT=1)iu9*Fn2wP z1Xd6H_%d2y{x0M}!kj`9{TwVC(CnVwg?!)Qm~Mx=w#l*k-UkoOdlzzf8nw{|HfX(T zOpz`EreFkAm7H)3ojk4!B_}{h$-}_#6;_IZlqPn0)t{!j`C-v~SrM8?a(7uOjhq?N z9;j*vG#9Zo7??rZ<~d}~hhOME5!y)~z+^Sl-o9C0N(m78X{ zb_b%_$V@DzL0a;-TX(B}pvsd)TYUT#@uqeyUc}g6C{f$EZ~N#S{dv=Yr3Lq%3w2Jk zWi$uPze7~9ZGKt31J&UhJ44s`xrwHZ??Px2yO0e~v?+YQr0^a*0=m-<(QR-SQolkI ziAGC}cZY1f`4m5Mdrn!ziEf^BRK3Pe3Joq?W);1V#9N-{ zjIB51_~4V33m?`C#nc#llQw$ubBK@mUD4%d7n47~f-I>8-A_2{aCKdLyx}SmHC!z3 z8Lm>x(}GTxkNZM70yb{4CN9?JfxAYE;@=c%-hSR0ee(K&o;1nKwX`#CUh;{CFDy^N z`vNvkB!9OG?k!KJMpK*!uvS~gYgGwPo%l;1!qMKRo~WGQfOD#@$uXD~wLz`%{U=0^ z=6m~ZMqpTwhBcA4+KE0nxo{!9I82T8H>rv@=Z`iRnp^9%sGPSt7chuoNyW>iTwUwA z-gF7ks15tROPE` zO0IIZhsxao3mbMi&MCrPj|OSW~KhkjPYn0di8Ff7yo4lJ|{&#!r zyoIC?K9Om-R-eXMXK`EWpgC5FHrMctMRB?_hJ5l-aamuiSly?Jr!L`%&VU1vR8qm~vH zI%h(9r&a$+?wd^`ON?VGj@&0&o?qxb=Alwe>Q8e{o!9k}?vFZ?iHIsY&7*elqITy! zT@>@zre9Bk2frpWALD&;xh1~ZqGcBnIp#@5CL^DamZHeE-KP(Ww;eeDef`SCmlwTV z7{Zj<2MIk|gB4+SJtw$$Ho)H$jZlj|HyJ!UPCkm!xN05MGUXpDXz8TYfBSRdS=kd` z6nZ1Px%=A%1Q6N?tdw(8Uc}HTx&I6yf2;x2BqJED2u!O9B&%G*ShO zLV-D7f23;X@9{&QfdcNTzvPJCh1g@z6p5j3Z!WMC+RJIn9k!`l%+af`yr23F3`-Uu zK_2f$m#G0;ihq-XObUB_t&)gWy8ko`{i`V!YXU`Bg@`G9L#q+%)cw%>4!ddb=vHW}W>psdV(^^z=d9-u0Qo zT*#kY9lF`?g0cMS$k$~%Ce zYL+4x7rx~YsYv^2Z)2*3;CjYpMT)^@)Mi{Vp*n5di8^Tz<#x@W{WzumiCg#Dcj7g< z{cN9N1%g$xDs?euUov<-Fv!|4R+CR?Fj{NaBwxr~bT>_S)8b>g-xoZXwEW>QN~mV1 z!=OaJR5Pl-@NgSP(Xf_E zqi8(I8Y++>cIRIRdw$T6rgTsXlA}QG-MMne>r$PoDBrS|!=`{^#YQ+*>Z_r z85(Gp_S2+bniL&;J=!Xq`mSod?|i3N=p@+C`sRolpVTjrVZ=d;Q3UzW}gCyk=PLf$kkGWTHTL2z+Ez9J*=JuK0gx4)%AQT??|qP z(X!^6LRkPfQNis-7wne@~%bKY%Hn!mG9?JU*v*+UP25#o|aX)UfgLbZ{aenIM5G`Hz!B> zJ*1|_z=beIp4An_`=!5?3OP9)ggySQzZLW%+qNrMlC#&2mRdVR{ME?Cmx|?U*`fU$ zvL2|_o(-;88ax1v0En06iz#6)@;QV&*qVJDsv^vh$MIUmwXdpAb8e0X2%hXN&3KZw z5y$d%3(i;T?KJm}G_5$N%F-2RQG4ECl{E!T6ae@Z(ISo)$Q~c~*4E^P6fU33xiIE( z6jF){cx3~#d@ak)nYw`}RE>BaPmeAIBt zqlH_PUdUc3!P+YX1=TfIb+n=gjhHH`w$hU5RA30V9&u|>k%8JkZS04Mms$^0)e8K| zb#nZ){X)(31LM5Hqb1kCMV8LyJQO#bA(iK6w{@?kXgOf9ul4jFu=`({KP-S!SHRT$ z0%$dXH7bbE4?IbeyUx21h+Yu?x}j!J8}$gWdX#r{N0I0-B=cOAXQxVqywi*tN60_-da3cN zdzN15FfrS%spBm~(%z8CTpWesOHTw(`>Kopx?d;eoju`9ThuY}#31%f6m??Y!-by3 zQbg;hQRL6FTx=u%M4e-_TM)d#Go@4NlrB5?l7Ir`&HOX_G>h z$t<3Yv)9zZT7=vlFI*@y|G=6xbeZe+o&HFIC7k# zLD@h_H5b`Vg?l{q(jvim?6O)8L!#%27H!HMF~swd+NeB4nhQ!r-|dU= zlS3V{K0ccg^3i_LY-3XBQck<|qyFkE4FMOKR*y42@PCHNKqb@dqv_7e&57DEXpyN$ z!oo5?;x6vH#HV8!^@d$c?z*HT*SFEjGbsh16(V2XSXsC?ute}BjM584@aOm#f3Z@~ z#JHq+>sGG`I5YaXxkW|PL&a=8wu;k zbc!qGec{~6i)GpTk*7HGnwc=?Ap2YHbiK;S)2_SX&HH0f1`HvJV8=h=#X%%f!?k6UNLz(D3?zLH&Wb_NJCbL?~yCB8?yFWRGBlI z95WqADlV78Me??9aC~Mp$IZ7CN3=H=IWX%Q-(}Tb?!Dg}lPs zR^A=ej`QXQ@m4k!Swb?M=5;4k39)?0Zn8k0sXrm~`sn_ER6~eh@X(z^o#TgKC8Nw|bwE@2H`;U@KmsHb zC5Uc;Z{u(P-gj)*|LO%!{k2jIsBER3^7GFw0iv2w&uaHxyxge--1hDKj82H&*;<4*047 z1wCc`2(TgoQ7FODO8`Z8P6h`fZS6vO%0!@>YPfCGW9!J0KT5Cvawf_T^ffg8OgH$W zcz|%H>hB-{B)`M;BVcT0S)5KYmgT@rmnHxG#yw`xTA4w~2D z;|sZqjw8gBpr>`-MW*#_QwZ7^+D#~CgIY@B{;J}-ere&fUF=KkyRV80FXh8!NsE2O zeWhm)ACvYE^v~y#a~Oz_-=tKl-es&E4|4M>tN)J*?-aPM@Za^@UVwjk8R|6WTTC&S z_BF;JwGd5yzTU>QC$yd)tE@~P*64avaXy<_KW68gQwrjlO;!+NKw{Vfoj4y>=9_>w%8Db00x`C(%%jTk+tUXBcg6}mgPnnZkWz8+nRjBX2ON~W}=}W%niOaHd9h>dZ1{5WLC2@O> ziRS*j8##IB)Ip(hZ+~tvW!2e8EvB$k8m2WyG+sxX9(XY+{|)zM&7G6{_VI<-tKw!v-g2X+Knwec*iOF`6J*y=S{d=DJRpaq*c(Oo*4=msTrP`*bP&-td? z+&V{%y~5wb?t7)!HQ+G&O-;H~)`#uOIpiF-C=GZji1i%5vY-BA>u3kBdoQSql)j^O z5ja@gWFS{U_-zzh&PjeOz>P#{$o!gji|(725p1Oee3vyD3O97t*p#MDz^Klp9hA@@ zx>oWcD5w0UCCG*UR>!4KqC0R=r)BdN;}TN4lk`I-A5@CXEDI%k2==>oZ8#EdRI24Q zAYOWQspEZ96JOooN`JX^T#)-h!rFM`m6{sVV00G2oH|9d=MO)|W2k;Ej73SAr*T_K zPfo3vQ5|RjYo!y7iK`5y_c;+*qwV>lZ8Ey(%SL zy3Sb4T=kdwaLGV^Wb75bHQLw)r<|TB`@U@k^1SJQhz};)WFFg_={=vrT+}o=NKci8 zNHIJ~7VznAaNDlhJyquj|d(tOdDE8G5egIu#?nsFZoG$ppQTxMwn z$G}toDm*cSVfv5`&^%kLx#+R=gPy&E3Bsbsd|<}2X>t@k(gmTsOYwNx!BZiaKC`v` ztqSv(CEF39q|p>-`r}=QH7&n^s-TE#+u4PbQf!enc`L+Ao><>A zv~&;;kOM&4xCfk!RYq?RH(ao$Xp;fljZp;EoV9y9x)~KKD;@2YV$hnc@8DrrQC~Rc}_*f>1p`cfpz$; z4uUl~Z@mm@NxZ5?V?K9*?Ri~%>(k6vh|+R-$|3&u_1p0 zfZc!KPWarvL%E}GFl{cOIgP$FckIPcG~ajzr!2u`l@y$JdvSjn~x3E-$GG)O7IXh+Jbb z)zo`$)MAi>-x;bg{Ov1!4*(=$iKTt}9-`U6l?5Iv~I8r{4xD>oYZ?wghKQBZ8b5^K`vg>{hbc5%x z*u>lbXUhVcjIt|H`kHW7^RMInWw$s#47%{7rNSLS+s zJ-|43{irgTF&aj^VEu%vCOf47m#D)OALcRJ9)ZAtI5wAMdB zOapWgfv(v0mX1$2esvydW2;}Bd6K5QxemO>4h#K+0+BL>?_~icplcU0c^LT?3-Spm z(3gti%j>}8)F=mG3_hRgeuXANPVvD}7+KPM;3Ky)hg!MUi3}fODPIqv<=0Hjx741! z<9#X$yTBVDvMjOT9W+Q1`O88>{NVzySxhgOb@t|)QzU3+(UsaLkrYG$C9bt;h4TE^ z9iwA?`J?w{g0hwThFRAQygoEF4yqY`M&3I`#R*ZeP~=!% zhXEf{#v`~mM*mkMCN3iWQ+dEd!Lgbz5Qf*QX|VRnV;_E2V#D;cdMx2~T(Jo39;Sg^NYTb$I1RpLcl` zj2`F>QuhU@H6lpeKXBEgzmo(yb|Dtf-U(1m!!PeJ&UwX6H&UljiR;?Zw%gLk((`T^ z<}%;T4G-7;GA?zUht~X*v9rl-{ zhA8b17gOnmTCZ=%HSo|t0w@w$K3~Rnx4kXd1Z_v_dvs=C$Nb=3`-zrkt zDe$v@t;D2k7UD)b#uSO(Lr{&)8c`|^M2o~$V56@JRFc|~5q7|POL|Go=Karfk{OAd zJn(N7@;}N=v$hdnk4rF*T(y>YK{Tmd9V=jyp_l(DQ16m5k1{90@_xIZ*&`BdAaUJJK0`CgCiP&cOwmDs|wSHfFimowPUs zeH8wyLp#H-w^c{sGU?g2cz2~9ET;1Xua79A(T;X;W}WZX&tKlJ;0Ax~_UZTLq~E9F zHru5^t_S4)tE@XviS);$O+wygVk|y0S_6&jKJ%y>_PGJiEWvfqY91E{dd}KZD@(;D z`nltL#LlrKpX>9JU2dyu%ZU-^^fz9H9RNX5p z^m%v>eLTNtu9xJouQ+}Kxas;_DFVxd@|;$5EK?3Z2+*Wq2rogpOLPZxa#^+`a~LMX z!|9iChDSlkPTYq=WgI%Bi8Xa1NFL&gQGh`wciguGOI$q@gi?pst3lsEPjkqoEQ%nI zn)akrJ7-wVJ}urg;j=rpL2y9;H`bdkeasNw^JEiMRO6^^IXTk0gEm$mqw$S+LDYI~ zft20YOYMA9_N#@@`}a#8NqhJ}OcVlq8H(wJbY6ArYzgtVp0%(UI4p;bo0WphBo zSlPq$=JYrgWi^!O_TeS#IOea3vGoaXJ2JVW=HX#pRGx{}e#l3m3KJ2wPSyvaI&#i@ zwV774m9F;#W)t|nZ`W*$c#T9%`+3)NQbCO*IXslCzd~Vc??0{vxSc{Ksmd6ST*)(& z3d0=teC<{Al`-?jIt{T18PNQRVY7tJVXAaV?pQ4#+>>8==jar)19g7b&y>=zsnXrZ zqo@<7-;Dmr{jo}V;R~nQS9Y8X%W!8HuPYOYpwO80vv>Z*`}^ly2s?~q6!?-legLUB zFBnx>{L3P+)sCouzHqNVuR1SZh|E)E|P>6wc2Zu$>`r)xg^K z>d1Al6&4iGg}^M7?H7R}%{O;zTCpelJ2^(g#A=)ldd*hx5t)_CQ`3Ph#tM(dvHc9G z_f^YLsKqRAy2jbqg{`PPCz#b!JP0WwbQkTW0mTPo4c*+@v-KWzESl%&a|F?)+geii zX4|@u#gen}?(NA_&FjYy=ubgYDdG3@nF9$n91tafn}9SYrc$4}8`K=$hX0y9Y}==Xf_722jvQE}Ua>^uX-ljh9!=t108PY+OA zxC^N`7GIOL?8$*Iqo$uVr`8s%wr!R{SF=#t`0(`kt2i0`KNT7NwOIdx?&YRsakw0* zm_)Iz>Mv>Ndlq7PhcN1NPCV}NgWz*dM}8eNlPHi4F|c2|SKm9{Icwi8e~Xi?PI&uB zWks6lvT}Me^O?;H6f#th$Xon*#I9`9Xzb(2Qh`7e+_--FY2&I4ky4agBpxTG0pn1S z0XaLpk-U&k;tExv^2~a-9=EjEC?84aW!2 z)L@G~!=Up4LEsT=sUQ^5t$MF6u;uAVcqav?t3DB!FpNL6eR$Z1SpA__<&ef!6x(nP zL$3c&0^ecY3x`IRCBRS-(YN4+YdxlYze_l^syOo6O)aMj7%t~BC7Tv?iE{yHlL2p) zSQ$657$!c4pM^~xH?}Ec4uc8mIJILJy(7`b$M?eZpnglBo>hxAgjlv=gcqCZO4q~6kP_E*C-Z9 zti!z}^^A7`>A836#J*;q3;W55aZj!zx7H1cNvMJDY<2NS9=!jvqkl9NnTDY60m4)o zK2)S7)c5qJQO}cJ4vq5n!y51-Ej({x^xl>~=+)6HpV>aP%b5!vw9q_KwHS#nmco7k=7&ln4x6ZLy)MW0e8vJ)T{m7 z5&K@GyX!+-7<~P8v{XRBxA3C?r(yuTZgZ!yC$)b|F~J39F@Md2WK8NHXS$OWqg@WR z_D0#3BnAI;@osu+s&aAz!T!{*f4w~mW-%+Lz7;8le0IQTnTyuHK>Spnz0Uge^Q@u? zwE%npT*FQ8*kw=kZn2A*vea}5 zO@QV@sX0uYqYhV4hx;2coBFq{K9}h0FDP5xeBRnSoYZ+b^OwIzhBoUk&u4EHL5@pd zA7SPRFDt5bJA`JtM5*tnQ*or|M{vh3VwcFxjOokwRNl#3-dSvZ?w&n;m_3iFxKQrV zjG(nA(qav99i#Sn<>EBFhAN&ykQ3=`jg{Ze|g&P#UWFRKt@NRO?>3y=K)Q;3LD zknRNRvo2dX<9-&}s-#FT?33KPiTckYt|UT68eQM-k)KM7eDi11&$wGMDvDVz5Lf!q zqpBgPg=uLIL<-a916ZHg>|EW7l3NqIK!+HN+8vX+CX$^(#c>1e%6^`xHoL)+YIZXb zkw@h=Dk1XSddOUsUmuucUunpdGF}`WEu~PHYHe7|tkLVTdG5uH5;BZnJ=@MhDY!*y z+zO>?<`~Y>(Y*>Hc_V79io9rH`9b{;>{)jZ+=DxUpBn?}R{8mSBrT6_SB`|YV9q!@ zAD3}e+-yZ9dcN!!G5yF(`3YPGWro_w?xKoa(w0nQti8EK^&);q}ve&t%hwCoBwKM&3_(T z@IT;X`llbsQ}7vVK4GgO(s{|=6c_v!cK&+&D}jK4kOIzaHA&tD@vIF4!*Sxce5TN( zH1v~?X`B^)9K{NZ?JyX2FTnV(`pi;N_Gy24?sBc}vi9Z^rR*S@?dV|7hW0l%c%fP` zU!0B%#(6m}sNojMwIo?JURw~DTK3b@;4h0RDLNfx`>6P2rMM`LpwS`B--PpSCHuv| z>wuQ`)C2@(m5nzKegrFe=*@`f!z{`9m8|Qm6rmmkRs(wJ%nev@$Sy?I+@Q&PaE%lA z`PJZlSsmHWhL}>dU0vGx%~cKlyk6j4|1IY}LoH<}U!a(%lJrzPJDW~=0m47NmEzfr?C2leipQzN`sW%1dC7?T;~ zM~Mm082Lt6jASLN_|TCy3uo>L@9X+G_ZNPpQptQ8*|I*7O|r)gCz~gl)L;4q)1BzX zSfKsZjI0L=CL;XQ_vV=dixa#T9yRB@ZKv|9<_VQ*98*$Z*(vo_R453S`5O7yr_p)o z{McN{lmXifSE~J%u?{tn+@BaTw{eE3f zdN3Lh4!``gKf{RJyO8seXdycxN+_`@Fy-JImn2UsH-ceAy80Ubg)6Z;x6XEUzs}0s z0KSqQH%}4Pf=3xTJ{T^sJ2onRjJepTkV8fgiAb=&<+=~i_sguMB8tga)0&6(#y5gO zLg@7kJ{kH*f0&u;B@!3wby=#(F~=vdmfiq&Wr;5X zn(90|4oeuOIhAqwG>mUN=K6MjXnWSCh&gh$)gwH8wJ#9tjv4;I%fnlj57LolIp`=^MwlUsvS)1_QUADAMy z{j%_Noy|^s#v?-f+4ZJpj<@{ie9bZ*&}*F-q5P5jMi2RCjo$tobqT+?+?RBV7?p$U;9NS7i-N<^fI6hT2ii1ecL8d_A84xx7m2uKI%ASEIoz4tCP z^pen0J)di4&+N5ktvUOgGiS}U_vN3ETmkas{odz!pK?FMa~eh(kB6bH%Q6qdNuqnRI~%YqKMTPeubGorTcGUy z6==BLTqijDY_<}tQKTBv99*Y(&*QA$?}+?M`vL#6(y8BVHvgvg{NL~8pUq_O-=1(Q zhbXB1sb7$PKTJTLa;YF!TA1vNuHyL*{%L*TZ?s#vLRec^Z*0hwY@Z1YRSSp90bU)P z0`y``K5-?xinyAT7JLypK|^J8`b0wHnJo3@f!cvI3*X`j%-TX@l#amKOZ-dw&ivGe zT43j%a{Ov}ZO$zzwkz{9kCMd9b&vJ?ar1o6z07?2+To>cU&#a-)-EQj=)Ilf^RoaF zA*sQd@HKpfTGHkeT1v<5tSd-(82cZ*%|_Up=eA*l^cgr+yE6Ps8ynf#8C z;d?^jWxGcy9uyYGW3$}5EvhOpYpv&(svO3=y+{ILwr1!J_36e%hCD~3=?}0TMUsit zfg4W!T>;K5u0-hs_r9v)!d08g3i@nnWXCh37m`za`)o>@6-CC*vLv8E6au#iC6}nj zz*L^&go*mvLYsQ5Mo4BOc18R%b?H=WLHX(>UoTT@P*!DY zC+MdR_2y1EbGSQ!Smm-gKR{*Q8@VS?o*!+8B=|lf)K({JqFqr#sOnG!UeAZB?Q(_O zJRg~kEG*!Vc*O@Lj9jK4!5;k8&Yd*XNy@jToesM`z5QBWsJad@Y%@<%=c!BBmwt2- zbcaFlKQM7$oJGW-G1)vOdq_@S2W%7iU_gzlgE3iOUzIDbpWZkY8gYz$SSjnyVu2F;iIJ;|58sa26#D8H(*Pr zl1V0;0McGbMu|iYK=#5H25ARxLe~ZgBi}Lzw^e^ZNh&T+ZE3 zv16{E)woTO^Sqo_W2%cSw6a$z91{lz%)WXkGl_SqN+cPOSj$PKhi2XkSRq2)H0j!p zSH?S*i^%w7Wb+k7m+uDfmf+Iz_U_4S45$`#3SfYN))M5b39VbLjfg0c5il}%K_4cB zFZuabKUd>7d&4GZ`JAv-uSP2U3ffGR8x)^pYwdn{>bdBN7>+R9=4OmVBcJeGyqIv% ztM@@2fpYf8nE}}qZOadgk3KBuRaV08TS&M1L(XflH9c$Mw!1Jpe@LqDu`!<$+@-1gGWF>WU* z&L>&NoE|ihS9h5(c5DRy*tpM8LE~D<(?%0L+V+wT-%jBL2+0hFh)-tI}$-dI=lb6-DQ9IJ@=#6 zgIM@9+z)*HZ=Txp=O6v$$ojbulPt#NTdfqYM5d7ONygTB21b&>(?QSb>T@xzvLT$O zgH$6$zXDsKDR{AI;raX(*4LPj2J0PUhB|Pp@3kZngciS6pdk(#YN1 z=5#8V)nEGxEoPZXV_6b>+*gHA2cQvtIq^UK+@(Lw_5Z>0#99+gkoUn0z~$`O9M z%qPYsdau}b-8jdcbE`|=w7U*)vK6?Gd1rArrjvRC(32MPXLH%g zixyp2Q2b5)diDWnWtifD9{Q}P_4hj7O_t;E>A0hdXmc#I;-{PVd2sxTPf*c&`b#MV zk@-&yeRs_V1&m=CiTqUrlg+M5 zQ}7@H_=D_uua2M3f3CxB`}^kyA=(p&!Rur~Oy?ggc9cKgiQo`Ccu?@9!+=R$gL|q(Dk}GnV)r(~8qem?)X4vYQL0kmpVliIjv5=ZVqVnOOE4R9BJ#9@F_ zCL>|xw)yz7(>!@~<%7gKUgNO^GigQ7lwC{|ILWz9fKJ)lJJagyM)#Idu0$Vy!kOW? z-u3k2+@zQV*?gc3nn+n1d4UW{dPBiJ52Id<@etbPf9mA^%L}+43%c&-^VOg0@YntD zmZm<2p@(ekTPJG6W4eyt;LJ}FHNWw< z7SE&W&2?8Y_c|qPr8z$O=&Wd5OP8|fymah~9LWJ6VikFz7~H2-^o!f$-Z7ogum0)x ze)_#X+yh~QT)2vkHkAeWj`G9o2Mtal%}TY~N_h|YmM2!!?$(PuJxMvhX4);ppd#;) z_olZ+P3_bZcJFB2cK>y{*ZPWQ#zw^$B|I&C0ImlYCPx+;LHE@&fAN5^M?XE_Pw)Rv zPrgT0(F3X6a#9kUd_JM`&E#hjU`86!Z!CA|_DFf)``~;>dNQwLES|C&NBlOz7rCwX z7E{f>+(R6wD=n+6Tn4Y`iNbLW&tZGfAfh%vSlT`cj4<7pu*d4a<|DDuQ_O&7Mtdee zoNe%(EHeS1&Q1lRT`_<#rdTrRG2$qT(7r_l(5adYfY-3V2;9H}*uDk`dmCW4SYlH9 zPR7$q&?1=~Qo#C3twHIBZv+I2qR-HN!&1DFF)k3uB4Tu-T=cY z4*tSDdkL8+(+Fr7B`Fahw~#m$I4O4lC__NNgbZuslHPZ+U`SW$w{6@NHFi>Q(kzh! zz!^Q-1<-B92-3syS#$xQq9(Yk;owd@#~BIGaCF;~qJYutJYe(u=dT-&;i{G*y^RL= z?DChZzLTj40g`&su*G#0z|3VU{)7Ej_2-KGT#=u9qs55ojW#-m5e z_(}NDU@y_B_2GV;eM$LZtblhu{iQl(S{Aj-ea!zDLewLx?8g|x=P7dK{;*l?TTs(N8 zz(Ch2&zbAOi;&Y5zBW&QXBxnm(Asec083%LmhM6)b75bX8NPM7F=qz$|J6bzy^BK~Um(u041# zAwBnBe{BYzALY{RwXxR@?sUBryl_aWB*2tfQmyUVl{#Lyn1hojLi@0E5}yM^HIU(Vjm!II$A0}uf8BS*-~UXij^9AU|Mf5b z6?9{{YJ=CQtl{FR*f$%#DLsBJHP->IH=W}Dl2dxrdVfH$VzPSg9o2|e=V}m*oIR5& zZ^RkthsR9soEdXrxM3q$0lgz0+ zN1LtC`k}r{kzTx-G~}r=AWwXt-Eza{4&1|(LDir{$Hy4^7-gt4!LO={o+)#-ynTi( ziCK1T!PT~jm*;}qhFn*|it~dfZvw&n;M{8KWrdf%3L)$IRM|_l9|r1L%$hg(a? zQ?whir&O4VgG^D!S{&LSf5HU1;^b4RYU6qEut;_+}TI+)C^lPdo zn{6)zD(9RJC8rFO3QxSZo4^Qs3UkuZ#fu8Z^PaqYsO3gxrg?w_&XFDok~uW*dhLL8 zjr+L$@T-pOwnQW)9{7ni`=tpJ}D8)?P{GG@PUL0W_#f>9fF@7q`y) zksggMQxNYbZ4;XWkZY+11Ox&b^_}cKOdH&3MzY4z!8(!%00l>`Ho(GHZ9YoWZpDJZ znCqk%QWl|7V;K=?tX~wAv!a!(W;Zb36Geqfo8*s?B~Fc86(y-wW4YyKGm&tB1sBVhm%w#*c@JLFGa-MS0FoV(4i_JFA;2!MTrqWIU zL#Gcj84M^)3VQDmYA}|Gwu-q+-4u_8_!5JIHu@$t+N$EWT1TlTzDVd7ntbo#Dya@YK~DE!qq)5Ph>`uh3?D|O?~moO$=!v>p5 z&@-~tuZrn3uBU1f{0W~ibwV>x`#W_>6Pgd4@8{cJe98Mb$|P8+T9nJK=AB=e2#StA zX?s!DA|=K1L89dGwtahS3$j~=5mYz>wVUhHeQsU21u=${oDZL_6PI%B%pUucaPB7f zIQ5jOq?K@M_LLC=EPL8om)07WNjqtH&!hc(Ticp9!;|CGT^6O9H$~k9SWmpr^tkY! z;)35EmzOTdG-h!1@-^;x!{lRRBYMkWA7%9dWX<1Tg@p!%R8>7LXY|ec3jwLHo3k*L z@?xVcP8`=Nf`+;O5+$^GKV%3W`ppNVSos&{h3Dt_WMEJk6gb@{n?lfhoWe%j~N7Y{}JxiwZ#;9slw zm^x=osbb%=U%TUlqzSGskdUk!R(zzs{*Q7u-*pnYi4_dqoOc--EsLB4jp$t zbA9teA4Ut_SJ->apGC!@DHH{1;2eM`G#5_=A4tyrZbfuuc?iNE- zr-r}E7DtZq{N1gg%i}tko1rFVR(5Gdjfpnk*i@GR{#ni8x|#z0iPqXqS%f2_V0R)J zL!``=C+A`~C=$TA<=;}=uMvW2x6znx9Y*`3IK2GO+`xHj!BLLVMB5`3b;`BaGc9=% zNqs}wMT+_lBH;|7`3+&-eGYBsu8sQK-1y(+7x(Q;XV=8nI``_9w!qGIRF+e1q8E2U zo7y_O6Ni*ueBnP^{p(2d-w^Zunfx|?EpG7$u=zeBwhkHr5kSQ=*YGK`SP5pZtE)v=*R$ zD9~^x&x$13`eEn}B$IN&6nUA&K@P<(} z@XqP8@04p4Pim~WFf}8W?-ZcF#b_hcaeKpe7w4;9TTx=iwd3n%d1EyiA!y|;Ycb4M zSNoxuw{|_S@I9ICLhNgJ^Wv_lq#2uJG(^lHD3Q$7mxOg$ZO|8k#Ni-@;0Hmm3KaCF zY?nAZN_4)Hy^>seQthb2+UJv!T6vlACR?g zjihVlE52qTEqUErQHi4BBE@0k-2bi-8J%W2ff%fSO-jy z`T2&J+58K?GapGC-^q$*i-l3$PR@#p`qO`WG_8pfzEKbyyqkb~(+6wMc$Zx|d#`?B z%e_8w58=t)3&NzpzV!;(GytjkIilsB`NlzN)v5qX_WLDCM_jFAA+Ne(Di>AugvKeS zfRp`fN3{)SIww+Sh2|EYBQ{Ksdzx_k9&8KHD6^T>ecU13sLr)^P5c8D6$P{q`;&#Wk9~NcC2+PqKYY6VJZL`<8$`2nLCM z+LW4e?B5`XfZQiC28qu0o(9L;o@-Y$%-NYVO;_K%RsFB+O+ht)UAi6|Y zk1f=0wwrXnA1NxTugaVf_#p50#7thSiISZ$SurLFbQNs16FQa=CnLM+JAo~COOg1- z2_{4Gl?A)-Mlvd%ei_I4lCqua64C?4Q|<-n*yhKYq9=@7A0`b?_i2J2>JC?%&YuXU zBS!S9^(`=XlZ>}E!)aC?~An5_n-`R`>7Ln_EkLm;jsE%}lvIgC< z4-sU0fXwP_8&RZ-MgyC>yzcTTc*gnEyAz*9jTgx3y0T3kMbIM6{ciDG3PoCaiAhp~ z3AtEN58{$*Mebi;k8j#973`YD_Iw?@#T3Sl?o_L+t*mmUM>bfR#pIHeDlo`5nYM%s z=TTqIqWsirU2SF>NN%VBd0AYa>N}jF38HOu5ybWui#9nGE*sK4s42@?tV}JZ)vjk) zOn`k^78A4)CSMO#Mwj4JA4%!!R)eS;eH2g{Tu|*Fl9MIa;?A6swV9A)rg+UV`P;5l z3BkkXUNkxIu3dL4T7Q_`Ix*(4(3`$S?MQ$INC`-+vo=fa5fzT69Z$rS))#if#EIQl z`|?&#?X>JS6oSTpE`=?|@h=tJ-#cb*+<1;CM@W}Z^zRa>G;#9ae$r>G1qU|n;$mB? zTtYyyya#RnilaQ;2&`5zk%GhN*~l~#(KHbYu7$Vm-9)hN-m{R>{>_oMzK#7NNJvx# zRADEPM}y)sJ+M&kb0r(dZP}AQXug3N-1Y!#;N9o;Sg@?dg#C8wzS4}ITk#=+dgQ1| z67}Raxys*OLX2TObXdB(7-WhdxFzo4Y-{!y(c<)ne8ubg59Nh@;?p=^y)xR%xisq~ z^TFRcJJj$T-K_E0f!&S8#CbY7f1u#-l&u9@Qrt>^Hkgl$Op}c7SsM9`&3^qvZ}60V zLmz36Ap5NtumqsTDR~iSak9zifcn0ZWx-S`YIWCPx_iW9*S?easC3j3bJh2o#tjRx zEP@)BNA;I{mFjQHST1cpM~VkQ7rKxOV8BP%?a3D6)DOInN(ivVh!X+&5UN#POanQV zG_7vW=!D?q7_D#Vl$B&~Pd2Fm$~=FNFa3xe>Q3IjVn6q0Avml%h)I2+Zja2 zfPt66I?MI|gwj%M?cMMBR~$LXF`yl%lnT4K*G=B7^JQDztUB?VNu%ETpm$KmYmsfo zmE`+|9$5^Ql<)SYD4Kl50|lq_ufk@>pQZxj)snsD_8+hdDjx^a!)GS=kB_qlbDR!* zzqb79u@xB$xrk3zV7S$*k8>dJWW461&&;!#4g5XOkv~33a=hRlXKxXqZq!?g(|)Ub ztqS;a36i?(0uNgFd3RWOkiTR%;wI1n#I~w;nYrIee6`P9y!_Exehfg)_s=3aq&^sR z(!1|g@pTAReFbC7vtONi>-f2><&)GV^V)OBUMYk{ndAIT@E6}EyzPnUho;h zSD^hKH``7!2hwexUEJIKmQVQil4pGttdvT6#2*JVw%>54W#+VUP;RX**%VPn=+;#Y zyr6s6Jyg<2OFaRl=YeOY(;6z?+7J~h9BDQBycw3a~*pVx}Kp}1ax1Hf?rED_v>6c)of_P zB*b#vNNaY(8JS3k3+WBmjNcSgggN@n9UwNn0So&tT3U~3X{`ZT+9;K`sG@@a_sZ*E z2Mc-`V(V0USC=m_bE&GHC7IzO`J>@gUF)#I$+ z642Xi>#UpH2az1sJ8y%d0qvGq4BPT$gU;C^4QH1}3@7W$N*%NTl|_EJ;c((fDTw7x z6BYF(jF<`pB52~(28n$~&rX`*|bN((Z z53doM#(`eZ5MFg&Q8SdMk?b>fgcu|3x zKQ6NT*q;BGoFP`gW)>`p+KWB!S42*i^FI5v%lUIzT>eZRwtwbZ|M?>R7vKGN=Vea= z2X5XwQ6frary`Msr}m&DIToWOK4&TvgvgSGCCtw3vp2W2A@)siA`S7l$qY>Kfff;x zz5+iI0Nuu`wj)u;2?VZ+VI<#nYT-pn#r`MzN}0|#4k%t_V;?wEjE6lAGLhXq1obT( zs2he-*YEZc7C}pMgi_2%?$X%Bw{N0+>^hs)FvBs_X3`nh^d4A+3nH$|bTHu%G~7P= z{N|B1`#cM8(&1%1(6}mE`cC#bo6yz^U<)I_%f11bz)wK_z?JhxqQ%%w~ zk5#G3cj~3`-MH+k?wl%C`AogDgJ3_Jp0ZvSW1*SW=mfH8k}`G@J+Ehqk%c?O_0!5$ zon^31Ak%;U=%m72f!wCY;xUib$r*E9h0rkc6W>sJgMl_6M*47{%i~ zi8WsuBLroPuey7hsR==fTBPbZO}Z*nA{=wMHV!4L2i#^1#lTc-9QIu-$O|ar(cViQ z3c84c2Fq@#*MAEq{vmiQ_q-Z(@0~Si?>kuuWH|A51MJwLWGQNgTBQUpnb+Cf9AzHM zI+oXd+xTp=Yw^eN=%CW`oK5&LQZ3L_N8D=fW{Q0N#|J1RXBP7kwA=WDJzNf0;&8Xr zP9NGsc+Jd#(tyvlA6OcOHpb?YCdC1ynNL~5rrwEFdiT?565MY9C`*0 z7BH%6sm(&KXJ*i@&zFS*(w*MCV-YV>;Ab&jy#tNh(0=ok`B5`BS6P zwKg%h0llYEd&LwHCyG5E8zIy!@mfk(DfGc!krSvPncnvRGVu}^tp*6*Om>pg+mn5P zZ1FM(<+Ie?2Xn@l%wph&LcT5}l^K!|q}r=f*-jK0lGo=MSB$=&1KNe(*eJdANj?xm z2TZTDMjJ&O9X+6~-3Q+g;9o3{Q&o-S7JbmR=9$l(PO<3h&lW~^M?t2Ql|L6sWBL*Bwy|1H|v2mJtAta1bGdW5M0j(V4Q@=8hwCw;>0! z+bwg77V5#;19v{BXE)c*AmNZ!XT*3EZEMps4swhH=ydi-U>DFcXpf@u&X7(1t2o^Q z$MTZfSKgO7r=6@ItrQ!+v*SG?0Z)V7fT1{~ z`?37l(^f{hRUfO%YpZdc=f;+tia)dRu6EL2KFh1=d49r53c?x8d6Vq5y%+I>WRlN| zk7vWYjrf--Eg(W`@iWGs!X-W+Ym!zM-q0|L_B_oy#dr6$)iI92T*;!&h{edrH5F`i zSv(C_J=c%c=pWg_NlNE~XjI%YoGduK1Eg$;1CN3Dni0ZZyc6kHL@r>g?2qfqP~9-W z^&VP^Tw4r(z&M!!D{uyL9XcM7{4Xxb-Uw~A`OUxg@c|s50)TSlhHWOh1DF5{{CMv! z{FR$bJQ4Nz0|N67iM_cA-V6gmbS_joUX6J4Lw;Uhn1q?b&0axCuQLZ{H|U{f(wB)k zgPkmpH@!JV9Uq(Mw_0mtUS8(&Bs(K@zKn{&BI1qv^^|KCR<6D|KnCjQhaN<`D?o%u zwraL8w-lM@$%ouF;qH6$!D+G!cE*XdCqYzhV^T~S839*pxa!b{$42M3OI94`=wyh5 zXl5w@ubE;`_?iHPs8{tVG;h#cvfj*=63RInO`m>C=5@VFmiPyC22n=8&nMhTaOz3< zZRI$GV5V*dQhN!BZHHi6jIrh~W}s+xRdBrD+nUOV_^8pyv}Zttjz&};5u|dNUrRB% zQtBeQskybzGkkmO+qw(Og?YGO&F>-?iW26Ty(qk zGFLGB49CIQ;X>|u;WiEVTxl8_q&xMbT#9*i=jvs2@z4>5EpFQ(=tsR zzlcpWibb@8GlhfqJAq=2Z}&gB_{PC{grE@gtjd7PrfFN$7&2+A+(0CskI_%#riJnZ zMC&4NARs?6bi#;hZt{a0b6CI$w(H^5p-PwU_o|k7*)MMGN$kEnZ?ghm2hwj4_R-+Q zkqp6vTiaq99|YeuWNv@4)tf_%gb$sA?K$2K23jH>-Uf^;2BQ<6wtUrDvMjeru1tlM zNO#5C1y9rxbuYVPZ7UjpeVHOfNJYb!Gi9Ge_a?cIPPA;it-&?#?9c{5zmqww>hBs= zWQlc)KeH0Dc~d9n`ncxmc69)GS$SW#_uaKx!Yse9ja8+Q0VWQ)M7$!X_@z_3wyG*5 zTKx1vY^-iH?bnyC9EgiaYHmVsz6_ST_o$QoQrSeVxm@2z5*FME^AA{{AN_h~6FDCZ za2*wFuycx6YaA|y-{=T9xZ9uL{WR9P(`TIdjYzXuXB(QCWZ6DuRSRyus=d@F>;DNO zNLa9s=K4-{eyVZlAc=EcV`b1sUjM>iVAf@dLWtd7cR`ue&D7(pr1+4{jKdm#PY>Iw z4$=fSS1J;9sm>3Z{T>z!=KN4qS{JE0+5Vh6s>2CvJW{xt+MFekgjSR^%Ko^smfrgM z)vD3}Ot)#VRltws$*$?-mhTgr3AN?7UXJhAFVxrX7ZjiGYrE05V)dC2?kIW9F`D6p zlDIt3xE1Wz=mcZG7W4W(BWX@RgIiT~Fk!^{&%wJ}MVECRI_>6{o{_oD^Xg%frwdoH zUdD#EXV{GhmQtz%=s5HKfmA5tjm4H{o^S)1jgi(iFc4s3;3e`|z9vtftlh>w-k-tI z)p?dilh9vF3shO$nJFenH0ZG{6uZ$OC!@57kDe^~ZueS);YY$t!ZNKDi|)t1 zEv~BxE%s(F1eDL!+~*LEI5t&yM{1wR(j+`YZ}nx+A=Smh{!EWHsH2U|(yl*pt8lWc>AYNf@U1{6>&0)! z9ORE2$I4zfxam;RONxxjyjrA?gET*%Su*Wk_$*QCgAAK_n}LO)DKH(9E?}PVRobWT zg%-?TxU6R}Js!S$cjMBar*L?H#kD2VmiMEc&)9wC-w;1nDbn9!Qfy!X^$~!|dde$8 zNF5<+B&yrYtDb64WNccvKM+!JHD)sDkxueW)|Z!g>auMPjQiDVn$h4i>?a?im~XO5 z(YJsOhRjs|JZ4(IZI$!k#%51?q1$l+#7K!W;V+hRuZ9_>OtE ztx4sUm3>s=3yi2wbp=X(3`>+;ZLkE--dO2e`+YT@!L`&-*^Ktqp^9L|qf84^9TRu1 z!c*fx6JzXt(&@+U=uT1Vyt5F3vxY)#52clE_3-YwV}KliuB}0Z@KHk&YI+}6^wBq6 zk5u8zbyx=_&?>jr!{Y76M-H+rj2p8T-dJtcr#7IsDm;}9y%k3!*yLW}D`HR2nWrBJXqd+I zSn60WQ;S|X@kfQpM>4Hr_DQ6=T8cv_yT-jZ)Az);U03rX<2g;@VvjDwLWurdq0-4E z(jyv&S--+^JpSKdIUtrmP)~_1SZVM{?u@FxHo|8f%J11tv8_ow%>hz(k?lr(>uw^< z9fXnA-F)Js{at5hHL%@+yzj^{oD15IGjG=y*3U-{MiswbKs~{N_UqBbRv(W%U&B(4 z5kctz)(dm(KKM)sCWuAzJJ}VI`6`^pxpLr5QcS~4V5ZVaY=$Jn*qUH?XA7Rc)VcXV z1_6g(L(lH+dR3uN%X9rO8ByM9bC4E#(!ikW*qD#m$l_@0K!o7S1x$Cm&GVyMkut3E zsC}Qe9m8u9&TzrOZV6!T647CbeyBFx?EDWs)|fbc0QPRDx2Z^-&4tb024%%RH(e6+ zn}c<1^MY<;Yww|RjULX-%3aMM@hqPYSh>?GS$Kt-iO+aOsk3-&ZO3$%lYIt~Hj6>9 z*y2*d-a}c&S4Q1wjk-drw!RsirY^DMpuSXW{7$!mVU6bN?PM&>erywOaQzr4q!mav zsenMgE(4oOoxp)vez$*6;>Bv`TOuue;=K`U>XS~LZlSeW8TqfAseIV@gq1}DtE(aD z1$zgJDw+e5l7x)*MpuqBXqMLvrH2U=v&@KIC_5d~Wu}vpcDz_;`{~!l>@T;p{O?~l zCGY&S#vYbc%yPrytMHO#{=QPjC%UM;ZB9yx4ttv!6bYZQ;e$v>>UPg8wq1k6R~_rz@ex9LsP;jn zP%Qnt9pAoXU38yNn|?{+BAL@UorTITwJ5GhMq2@C_W=J5r}!&Fo_a30sVAmPt-3yx zq&QpbTkM%dHEQ%@n2=~a*8t|sfJ<$(>wbP5abxpzWW88K>#nnHb)W7tv95Oz^Ev6!Z0yb;OcZJ&N!0sU>A@G*BoCoE?+UvK~uUrp?;mP9zg z(uk1>PzH_Y+aYOPY<-2VepMa$H^?vknRNHRU7vrxdjA*i{=4g_K0tL+q7Vy&@4OTk zat+lS?CK|7eB`H`BkMCPNvW+dZ*8QC1=6lgx^YHh7+TQbsJYHfXBT?!2Y%IdxNMTM z#b9@XQ{8~~yCr_=$3vo>qR%^n3IPZ!XX^d;f*e|z?@wVp6KfB`C7tQN&_t3u--(2k z?bQ%Ja0#nH<;{@P_4?YzZ6G~ec3H; zY25pvlVL~I6q$*Z#!1|^GHVeMxQG_~2t!GJClgSwU8)6l@t!Cg3FFFgmaD0J_wob) z2J+5+bgw^}Q1?ka`4;1Mx;&9^BwV5Hi3(pdzCU51 z_E5~?W@$P9Y^Of@rPjysX=FO&uo+PYq-t%IPf@pUu+F6zsqmRC(+$_8P@}6| z5Gd&`8%dRrjQ|VFwQ&M^~cs;38%|{dnKQ=b6N> z7iF{Y9+p+Yv85s`W{T(E@12r8XlTcUpdi=|4MLKyDZmyT2wP*3 z9y%C3>LM;|QL!NLgGVdPK(iMqQP++I=TsIhakplP(>Pn-(WgFKx)#6#C6 zHD6;>RublM`p^z+P}Mq70@h^T^h|N~Rq}<3zt6ZgWN#^T{Qby&=f%FrOUqe7lLvud zo5Un4xFKOc;|t`y+F`)MDc>gC>`f9B)^kO`&(v|bwVH(jG7SE=)^imxx`a9V zDCyaPH5Qwp;{BM~Av^QhSmV?wMHXGYMtOsh}eBm3@iJeu& z*@E~bjpg2DwZrAs#A0bwUUBw%M8qA+dp9}TULK}RrEWYq>|r-7xLxOO`Ay0%eaJ#G zs~M65q?^GYEaxVGRRP)^TxLC^AA!(N2|EjQ|3tmzYY#y7QK!6jap!t;jnr#A4W7HT z4xZ@qF_|brdNNQB-c`$x9yJGts$lWg z;!-pxOFai8=jnGqqTQ`!3I2S}y@Kwa?O-hG_7->U3b(;7cP}F_fuA;e6Tg#*ZxPya zS#;eGCf;^s6KV{f3{GUfXxg}%Es)cOVN+V}AIFGvS{7yjU-?(HWA;r!pqaA_9|#`; zzylyLECq(zkWe<9ff0<}3agl)65#HT)J%$rr0V*B00uJdNM;YLp+3Z4r34{o=8U`f z6z7SQXbl3YA<`|#7W*or*AlE){n1$T-eyf$$0w@VQxTinRk|MzQn_A4vUl0ZLMFC^ z+&+Reu`)?uDUuS&)pv_zc;#SAQw;gmcI)}h5N}uRb>9orr*4sdT5h&+@tpDIzy^bD zLDA9kbGpk!&$TR_ zz#Y-n!1l}%65J36Un_xZAG1jOKq9~%`7FiT0KMoPqJ4;Ss%v-)1i)MMoP?S%D|Is> zlk6^utj0ZTxePPkN(h&qee(jzDLLpR^hTBAgC{i-&s=5pWzl>}_AnXNV?=s3gKg?P zoVXfQwNg*hkZnupdtpv4b_Hym`o7*HFMK>;av~#H2(G*VR#mcE7HLzGD_im&sHPs< z#VOpT(00u>o=$vuk03Hr#5E1c zsps_f72}DoK_dxsO3{}A6yGhW^>563yn6kVx79dav&c7n+ou>z(y#=uNJx(FWT(MW z#UtO`ECgq0J%wP{Zjj6jG`e>X`=nzwLsWU*|Hi8$89jDA4o{ePGi}3ZVT6?{7pEyz zBp!MtJBtCwKv!t6FyLU}LP0tW zY3klB)fDA*h;y$n9s!znN}Lxn zNLpA_*OFyFp+0XaGb{IIdGa8~*`&4(TBO+emNSSYKn(IhSk}e&pn4T0dxwC~1@5jC ztVhDv3~JD$uk>!;>+--JUgcbuWi@=rBUMc2;Z^f7TFM)9p2W$X_Knb^(pHYQ$7YlS z9f$(HaD}Lgv}}=p=8Xx9%fR$6!l>Be2a_ zpkThx<|RnnK<4A*S=w>EwR?3TBqyNMz&V-#TWKPtJ?o;H0Z<+BO~f`wyb^wJ2k*Dq zi#_bc_bwxk+OvIgG0q#s07fYp_jId`Bp9&j9fS>ej}Ru=uaOM3WN+28?hhx0P? z8iYTxQn`M`BSVMe6tkmQW$ykJH0 zsvIpO)6RdQ#P``f?uyXGy)?N!H3;$7k{xN*xL~zg;KW1=z38h(DU59k> z!lGrWtoc$k`9iWBC`6BiS=*Ls&wWM3&h=t!XIsG`HssaVQaU78B|ON?q%zQoZc_!OD}DF z?@Mp@BntgsMH%+TwB9Bkz(z?F!luO0*8Lj#26%|{fNUGqqKfx?$~eznm&wrI%8zo& zw=}jUg-g&*LTKnBWJU$k9Y|WAmz@vt0Rz76pUl-17lKh|VQ5POSQq6i;f@7ne0KNM zmOxV((6PJ%M17LL_Tp{;`t>iY0Hzbp7i|X__!Xe=vKKcqf@`hai_ZjRaT{PWFraMp zRZVJNBQdoDjld$aYD>W(b2!Kiz(h2lrI>D5BIANlTQ?QLX~L(@qRupY_8Y5`%|{E_ z>)}>-OUceu-M+pf3C0b7DCOSxGBR$W{;S_|_r)iJW0?oIu>9OpvBb3@kj3Q_?k7T< z`WGe8U**$5UWyD3T{JVGOb`a)$c_FGBne_%dnbFuP}XKtT)6DX>Y?zMo)Y9O z+pCVpN+BNwGz?e!$V3f`^KOR@a7Bp9H0@(taZ{}vy>X2TpIEAVmJ07qLi$i%UU(H9 zD|7j~1s^h2Hk9s)Nm(GT$cNv3I2OPND9D2f!I-EWIcz+ZAN0;tVc*nGV}vygFZ=Pa zgH$j_;ls@acf*gTvQ_4xit-EibA8X1LIOgjAV9mm=Quzx11SJH=e#7#)+D$&0F;Q| zhbcSMa;?j551<9Hok&8mk@0u33~JmfznfBC1PciDA#3X2hM_0{@$FRvhT7{pndWxNb{T;1V4w0u>5U_2 z;P9z#7)l0=erAn4_)-O681qxw4-oiW;={xCstRP?4-g}*rNr9w?|~S9+1vjgOKEz= zORY(ec3JCw!YI?_D|8

}}IKt_e&h@=*5*izX7TMj{+3_ABSw=h{?(1O$wdtt+k4 z*NrD^+wrib8Za=spS0A_0;hS}YwS1Z4SPNGU%2Ym(BK8HnLH@xJL3(k6NAUj=y4c9x=y{+=mc_Vf-@>_(2Jh%5?~ohscem_lgE zgO;x2yA{#TlVCR@+aF_Zq_H$fs;QeMSy<*?A6!CQ4Xy3mr|Ty3bph_Qv{F95SwrQZ z=_d|5A0LU`Wcw?p_drWjH4{L^ld^Bu^*Bigbx7wGeTefy;}JZt9vY~@9%`9xwfzyj zix+p%F&P;Z>$C88%z=QRil+8FTj*^e^l9|k4}5bolI4q^qCX@ogOcG%VBz9TQ#&2p zJmf#y{< z$$r&Yiv6eol(ox+f|DMAZ^0&kOC)JjI={;z626la_#W!z0n+toq5vWMJK2ak=%8a1 zwn*%8V@@WqlU|UpQiXy?$S;trBVx+M9^^Ba7=8I zMt4NrNAT@AgZfp`=x>9Cz_{@*6_!UI@cg6<-vXp+kI}-R*tcb$c9P$LqVb}+?1MD{ zzndX;z7>GE&|?Lt*`c%;44r0s%-jR`hs zZfI6uLW7#m5X<{?NIE+&*wFe=*q|nh+(GobOv1x}l3wW{V+o6AP(O`ZQKx8yWI%;5 z+!o}B2i6t31=QE6v552)@FEzCOvh$mDNr!1?u<{rcMI=M1+J~CMy8$tm~mbN=)IWY zyPd-~>NS=yiiQI4>Wx*=L~qI0xCN54CHgB$2Lp-Q-=vk*UVkg3;O7UgnBDFH>u`(Nz6cU+Tewl)kF zP*D&p2ntcUf*@T45|u8}1*8V0NpAwu60v~P&^tt=i-0r%DM9I7=^ZHvoj^hhB;kA1 zy=S(2_RKl&_s;AyXI}r1pMfXse%8IpbzkdR?2U(}mC`i|*X^{r18bxbBSE-`(iSh7 zuzO8M>4}tYi5}b~86VC}g94QxvlGB9u^~K&_+bRz(%4Fh*_mAdd9gNQe7cbES#D_o zf&r_^&VYc-qPl0&#WqALivKec^6s>E>A>C$SsP2H|e-0f&Kj7fgjjn)7A*U)!#K^^Sk_of~J# zj{C`1!9czc2UyPM&YmHMSH^2wlH<)gYSpWjzjNm-zq)hnZ|)q|{?X}cn1=yJES)^? znM5ERD2pW~M@sMi6{+!5q27Xs&y+<B5})qVo%#53_uS+| zLMT%}=rcxS1NiV^TEu50p_A_N2MqGk94O%$&j#D`elFLurPWi^A&9r;6kaXK4kdB& zhE5%z+E{_6#ENA_r~2El%XEbC30ww*{UNmN48%2OA@`*CdDlEx;X|8&<*-C@o0cuY z3hw)0I_OOW3AgJepSyKN_8M|ofa>@4z23L_zC8IWSL_vPRsxPQ1-_qcE|eg_|CeSd z=^Ws%!gda1Cxtc!GSH^j+KuzUFU>oQ}Rk)FuFH4$e*W5pr~ z@fZWIj7!~6>5sjdIae7jvi90`yHy<(JwaVV_9|x{?3ckl^0P_OU4#(7z``#hB1A9W z|Kb$7r3F{5J|f3((P5jdjuh$+Zl4zXXy)0rLOCaSNpzoATRVLAh-jQBoiw3(+Octy z>wWM#-;?Sk}0(!!V-(9~I=Sw|pelCczZR!vT?V23&vMH-!dS+JFa$6x5xhWY!n{st>N*M`p zG&ME@J~P1K_ER#!A!5x^r0ZSA4PR7l2(p3e;SEnOb}TD`WChw2b|E%~yN2*Xgba8L z6dwb7MC`$j2cS9L6&CjJ=c^U4RNcmjC_Wz)ZtnPWaZK9{!p8e~bHz^Q!NW7haPl-j9SQ>q659d-l2vyJ zwN*qem_I7{->ZJIfN=BM?6vEc?6vY+_KE}EQ}oa}vdd~iIa1NCYKqI*>k`xt^0T?lHNa z*hCC2dFg}0yeDER8s0O0M&Sd7rG}d@q5gCGKlWw4kM>`B<5R zTypUOOXD|Dy{3WDnUT7Qm0B;G3;L zE)^MpPWgqi%vbphmvBhh&HI65`>Wo^9>xB6LGt4C&S)_7tHv3~%)8hi+E3Ls+S5YN z`Y(azWjb@#mfbIcA2@*@1wYsYhyQZn--@2}19WK!K{yYEp~8~S3wtbKw`;c;?+qcx zy=er2yRZdFkWMH8WNQ)l#tAVqFAdT%7pLu%7l*rq3O1=F68~~6w5o{k=;}^(HfA^cQt%_q*W5oh6 z9WF|h2b3Lhj2dmmBTDI-LmHiTn$MU=sojKaX(dPrv$wx}(_{^+C0kv@A&ArOtvm}p zJWSw?vLA)0GJS0Ws`QDB7bKZv!Z1 zSB)Y!knZyy0z~w}DdNz;kY78WBEjbt{Z6Ba+v*<0;jg&igJ1Ci`oA_Ei_)IhJVACI z?^}X%cLbyCnMCGBFmGOx-(V}QC7o=6Wb+=WG6@~Jz4t!_#s}t{AylinyVeV*3`O4sr_x&=))J(KZUh zjGpVNfP8{Aw@U?QwIs`ZvY>yUQ~M)I@F$O9`m{^>}##QTN7 zw%Hc;S{m4%0Yg@lbsW-bF5#fWv|%-3EdbKBWOOA-!ig^8L}BjTSGXRG&r+f&-#_r7 zKX73G;X3}U|NW!q{?C$3ijW*0I*VP*f$u*(FHX z+hf6J$?;4PV%-NZdm|Uz&5qR+ z9(rS|7Sse3Nx^#Xl3`V*;I#avaS89H(V^k;2LYj#;P5?)0p~r64_ah1i|Ow?l5-OT zIZ&axqxRofd%@V zC`-G9caLS+Sa*FmU>keR!~$ zagw+1@zGML@^zn(VaHz6RU!QAiEaNyH&2#3&I)x%u<>fW_Z|h{Wf}PSGir#XebZ0I zS}vMr=Y}(_o_J}&`-NGk*40811I`@^5)ag#fkT&UI)=pTslUJt4u6KsQhN7EO?o%w z&ByeYp7OdOTGxa6IDcr5!jC-a4Qrd>?&I-ATdq@OZ{B_%zD)q94Tw%~!8<_&jyX@s z!=-xK=(4hK-}0*Rdrf^&N1TGy_dPgyX-&V(sQ-3(B|F_wk98I^udc}Ci*<5G&XK#J zq3=UeopO!3UR%?ezpseKM0e?UoGCtm=c<^+hsSf^1ti!lT4}z`JpLiM`n3%Ehsudn zzbYq2W&+BI`d^h36VHFN{jG9h#p$v?+P&XjekTN2N6I~lbD%3g2J;YvdoXLYRQ6fm z(QY!<%!hk?TNn?Nydjwom+*LEIM&F4OSBfXXzAD!#aYVt&=}(17_y}1q^Ho4&I~i&qGFM`rF5huvA+? zJT4MevVD3)SU+2P8v>1Za^4=urpWwdsVbLzG~@>z4Ui?I5qyy4zb@*ffkrNBvh&&7 z-Rm2~3_SXyfo$kR8o%XvS)H4DFT+FI))>^2LvG#CxY4mh+ZSy5Wk!_P?cs%(BZzOh zy`}sh;J*OCh4H|Cc(P+(>A_!2aLDG5GUpurh^86wlO!+q;zHmpm)1!U6g07mJ_(^R z4KG#+tWa8PX&J=)@LAsiZiE#I|CsC&;-WPn-OH7UiuWjfO)XDpv)Obp8SvL0&JaQ zc&{K@*5*bfNn{ej5rh!GcSuI=ETja*UWLc(c0p`*5J|3{Gk` z9sRN)(diN27B7Y$ay}O!Bz-qUv;T)P${%d^2=nanZ`Bspzp5<;d{zuD z1wb9KN1;`gfF&BVb%)GM@9;-Y@!ld?9;l8<^@cCOr<~!ydlBLjK4XcV3m;1pc;uvK9|gRbgy3qQiflJvq=Hf zmjrj#5MjFYT9o>N{PFXs7l$vTT-`z%1FVG#ws}77*y%)4B^=_n_0h|`H%iIjbSZLLC(D>C>Y6tg@N@&` zsiPw|A5Y2@nZsW3wyaanqA(7z@L5n*D1?_7(ZX7AIZa=0M4p&3evy*S>B8s}>-N&I z8PPfBMAe>tnH&BenmV&-C&%GuV+C|mu03#6NVeOVNQ6hg<0An2#QUbsBYp;VxXzZx z=8m)!`;yg%Vu=~2MkH7}`&qa&z)6UT?s=DOVFm(96$SKndshJ8TRdaXW4e_&NyD1v zkb&0>Yr2++=*z56=lA=@Hk49giVqHa>}c8 z1=2g>DXu|hO8QKU9!~QWm9M;PJ7*nDb_gOF_L^)OdqbfD07|T_}L>SBi9dg)7`F(fGQx#|S6Ei5IND;M&p?mSt zu@TH;;(ngAC&nd%>?1U~g8W;9&>;$B$Fm)4<0YP|g&E3O_*cpjDH4x#b3*RB=1F=+ z6~G7?$RdJ+m3-9-`3`K0V)HikKJV1dSzH?~7YOY5prWA#utT3|CElW#Pv>-JDC^VyYmDpB z)1xzs4;fn6uPAID zfDm_QNwat;(X0n`XInZN4Z*{2{c_+aFzd^XKheQqD_`pKEl73#5~SXI3sSHovbG1d z4T_Iqm4&ktTB0|el_|Q?IDfD}v+NtYsp1*N{F0S!^=<08%FDF5AgjsM+0HT+_!|}s zlF!v~G8T-=!>a;&@+uAHMM1n&MV?i$RYnaHKj}dxjq!5^iIZWH_*2q;RyZ$#FwpJi z9)l1kNAn?}>K9qP@MvU|u{KcM>3zahO=3diIBFu!mw7(RozGS)Isg2UQZD5?EIZ}f zA^AnQmrX;C!toP1r2T8=T_3VSBe*mnpiiJ!P|`%aFwE8i;Ffi2rpY-7^Xa@T%n3cz zbdoB$YuEu7*JC@iD|6S?<2KoNRxYPw`gY5X5dnb7-T-y#=Er^@X6i}|K7iLlI*{}3 z`tUWlFG-+j=}U_1Miy~WjeL92f#6%YNAcq5xR)gPigd%Eo8=aAUjn=n$USG85ab~p z6wcYO_*aRrSZlb)DqRR3>H0%0rL%g9M-OF5f`9n~@z=L49T5e$8!s#WT6dg0`ScEX zxtJHk%?{#Dkt59@r3MizHS8-qu{~b}vHo)5-%14S^Z>LWAP%^e5o-ZgT~Fm8oxDeJ zhIML5QW%H?77%<2(5;j>57}%)kY8D}Bdj4chz+=s-Lk_QFO-s}+HWn15dTX#Yw#WZ z`>zhK>xclb#gQqvv(>KzBb(l-Ekc|RbhvV#)Bx!jC<;jW-X z*b}Uz!5k|vxUL>Zl70(4wthEbW$3p`x)=)72aVP2_~D(!&WTw4=<58+qqxBZ`qsmK zO3MMk0au@_HSpyh=xZ`zot-ENS5maHgsAT> zPoj^c>Ilhj8;?`zL3}!5#%WEw7qf+`0{vf{*WTxCG#pJ8LR}0yS6&om^Kuc(Riokw zYnv1oUZn#vtfWuG)k6HUO`vJ3MzfspG_!Z3*Zj0-sPglJnxgkMpP7`gU812M6J{J{ z?Phw>u;1h?cUR@)_Ds*Pekw%P(**$7ro=JF5a>M${m^#|?4VN{NP@Z`h6sLAi5o+kSmF%OnOlWSVh%QT#zilk_8dqL zQ)3wrxM_ZC4fcR3`mq$Ojq2nshqn>PW|JF(ZrVpV;}GtaFh(8x=#{$%6pbZLokF0! zr|}?s*4<*8W9Neka!2r2P6zkhj!?{Qr_5l#lUsT^-TU(M^d!M)Sz;nP-Cj$S>2Otuqm2@Hm&CS-sc1sOWpT|qGkEA2mib||FRm{#mp|-p z3-V!i|E@Z=`WEP3jm-{j2{hJHN!_g%8nnrH#W`QzFg{RU_sdOfIB=eL1!rH6*Mp45 z5G>lLKMOeS*75tV_383F_#x~2wPN{oj{{qmBno`Dv;8J`@n~Wj!92In%N2e{UKMk; zxn1-5Dn$m&!I&_(D;{RvB&A6_d<5b?jFsd!)VKl(QU+K#Qr$6Y1UPQ9>x&$NHN(rn zgP;n($M7z-$*|2dX~(IrTMDAg+TWrL3c|ZfFy7iJBRlqVG_^tFPbWMKQTDk%Zo^oh zdS}BF0(N>1T0A$l3qjU(QsaF=={^7uc-q{_FOx={eP zfW(je&Us^ieFb#t@VcaTfP+e*sUV`?Ri)Sc5+%(S7sh z|5#<|-(1M*^G|FH9h$btHzA=D`>kOAMPL~JtHAKsH-X{U*Ptr!CKK#crQm$tV0R_6 zuIa5MDSzcKnZzq(|ewy5tPn?K#RPE#3lcCNzH{d7^4W&!7=QKLim)D=Y} zpUA77LkF+PhIutML|NRoWxnlQH+vc0(Rcz=t+T5oMyv+qkG4UwI+MzGf=4~nb&?|MDqA3)mN8m80bpE{P=d*lm4=vZ8MAr4erU2t%$DP|wxgdV6heCY^z


_l9R26qnk4t?-KEjO`TejQ!u?<$(75m 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 eKCg3iMRS1Xk(ZQVn6(%fj=iYWIqoC$ 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

&fu#oJ%!+q2-calJwYzy5#wb`y_H0 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 k`&aD8buQe9mDWh8wbpqKT$KuYh_QI6&4@ij`iB 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 literal 0 HcmV?d00001 diff --git a/doc/va_process.jpg b/doc/va_process.jpg new file mode 100644 index 0000000000000000000000000000000000000000..540650418823ad1e964d89dbe1de5fd1aa5aabbc GIT binary patch literal 638922 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ℑHRH${vt)*1Te=(AwcUMQA(OnX=H)lF! z^n**v=0%{=)WCO6_C}UEv1ID0Ab1yl*5_#EcjODuVxY~5lNF8d87kMS%^_=g--{yd z$31CpX`1apd|=l+C8ioLdVhjkDz=+?(;#YhyO?Bt-&4sH>X zKQ$oJr0}g;rEq-GLfK`b5AudNM(uNZMGaOl;AitU&{Efsu?*iYEcIz!aGfJUZYdqG z1cZGRF$E#-d1GDn_{MxzvL$bxP!FF@CzbP|O6R_2fokv_F{zt`oueTsW_g`5OGjHq zY2^Qdy!Q@kB7D<@Q4~}}L=ovx5l}%8=`|us5g~ve3PMDr3kXPuL`8ZDy+cH#iGcJ@ zR7!vVp?8S1&|5+qNa7iP<$U|wZ};rkv*+x$=lcHfx^QOR_npbi^FHOi?}rjnMro2k zr+BM>k@Z(kCzmwc4^#>(t=2-_t)XF-%s)i**#_41sOEk(m=?%egoD5wC_gemK9* z_8kBD<)wLx=E=6aeI|+Y5XC!%e(7Pb(HgaDd~)~~$P~Hld0ZmYpI1?QY3>Sh8x@s= zT)6RvYG()8df!ibSmc_~4;D0fiXM+cl>C^x+NM)Yy^j&WcbjVS&qx zEAf-O^P5g`lNOQol^p&pmd~*2d;csRXodl>VcK(1b44y;_G8#or`7)jS z8SrNB1y{m;0X<&BPRq7oz#X|<|XIs7E{dlwrF#8q64&b z<==EYl$Gw|y-+o%B9f$O1K;x30P};s8;ABZiRpEaed>muUFb7EyV5zuGi8)?dJ5^#^9*l5aKbDS5ZT z4%e!X>hHt4`gnFP5G^QzQ8Ra6NBI&}~RRWeWo@B&}K71N$`75}4Q_6QkM-9G%exTAcmIM--s%7zk3GFr%< z1;*RBw%vy>A{%No^sM!<1(E`@o)ZJ?a~=v?`B!)3Gg|t0Ki5B#_~apl8GY_g*i(3z zqUaslLXStoOD<&EDBlI2nsG(lP=%6)9l|n3Ow)pg{e`q5e~1>xU<8vyY=z9KwLe4Z zw;yTQE%L?C*W80U0=EK{&R$Igd7k)UX|IHhZuypt6sZ@?gR5N6$R4d;|@(JUr8{^oYeM|1*x*| zfWPyoT9|IdwNkYHZG)2Fa%*qD3dJXGM`|pALkZXzNdha%Ns3yiCY6x6A%0~UseE6z z?)5Hno5ek7{@n!8eA%pCvZ0i4~MZ~5Peiv6#iHShT^t^rbFlmkeRQQeTlN*5cN?m$F# zT50ka^zKRZ+nJgS1}-<)UNK8|MWQOomiU`O4MYKYO!Gy4_Aj0R_lDcw+jBK6B#9MC zHN1GFv@=mC*>{VstR`QQjedlVj+>6b+zKaBDiK|(9n&wz$*uHMJqCKa9t*e%G}E-} z*PS4FzpJr+-Q#l3*sL|4+S@w(M)>E5O_N*80zpes2%B|F;ZYMp=p1^ z)I?m<;`w4zo~6_=-$;(O<`G@nB|cZmEE!2;j=F{qTv2cN?C23@9=pkt zytb*laQlTpY>>!TQ&KSD7kzZ1k>aP%PQUmpQigfaUJx?0laK&1U4GLYC-`ZtG@^?S zlPnjOT&AhZO4qw;^(zRK);4uo(vcK?BcpGMMK%6YlRbQ+!&5;K&$_Bq7|A_zM^^Oe zxsJvU=Sa`58+U}OO>utf-7Rw95O2A`==u%nd2`?GQS%MKMwq(uzV!qgvz<{LnWYejAL}7_bLFL;XOq&BGJCxY?-8< z;C0eEMopv>rms1X*59F~);-@W2xOHzxayJC`s`|%2ZlVNsmafyqrWTNH;6zv_w3o$DtVubP7Xa;&EDa>f9Vy`Q2H|+6oXKM7} z@H6YTNd6pH<4$&iOHT5_IupwXrmQf1FU~f;qYaGT#-+S=&Ubs}XewK_W~fTI zNWbrQQ)u8?<~4edytZ-4`Ko?%%hM-sE`Qt%tf!=O(mP>tvwqHKJ6OcY)NRU-Db9Gx|l2X@<;S5a<;Q|tX33Y(%+6G7(J_`Uq4bO zo#WM*^`@mBLu3M91v_cl^B${hDW=B@r|S*(D^3(&Je_MX!PD|1=IYmEn~GW@?~6obvsK5D^fL5F0&o4-aUIe z{)^E^u_iliA|i(mM(HIRMX8`Vj6d&2C5V{szYH#66Y7t;{Wz!?!g3_RRzVAFWmE$a zPJAOi%naZ!_Sr_QV9@9!K8p{d%PDL4PaTE{lNOb8EV>VGeDL2G%gU5PASMQg7p|iN z)TwREu|sni%`{YvU=LKfet15D3nZn9W-i(6nH3j0ZmL`}zr7XZ63zM6eB`Wr#^?Db z3P#eWt=R;YWL~^mz$b}Z{*uQ3^9_@b7u& z8Eh1e13me#kt+3HMxm)q-+NQ;n4q0h9R;muvw#01Q z4_~>aZ^OY-o;#ZG#V^ugNlHjNMvlLen~G-VDCKcE#|zO1!%0IM=`o72%z{wjAFnz7G9h#7|vE#^qZP01KJL{6_KiAX3z3Y=&?$OW< z^h82eu?(;*;Xq6`n;}j_J>(D9J12jhM@6@P0#Oz<=$_-J`!(jOhYRGg3a8s6+zvav zgR{WrlF2)^A`go`zqRSGla^vc^85fl=fJnN>x69yLNa;>jFfW~pa)s0m~G7h8uE~X zmMa6Oiy=p#k1&hY7zyYy@S9G@9l4_p`TGgkG(8+)mu27`m~LF)M~X{@DMSeA4f$z- zLE-zC2ic!Uk@s)>EI51RW3;ZyX4}hMf5RBT+ZoMz+t}!R@dS)WzenFri=? z9h^F3;06tzDGagwkq=s%#o3~txal#-O>N;*#{#8uW@GN<6>j?n8IFza+%46Jp8N*6tcm-QVfxw3 zK4pRTKcE*K=7sF^M#nonGA7LrRC<)WXMd6s_(9iy#D9XfjGN(;rvUb-$_BG;+jB<+ z38XCTjTa6-#IH(r%yC@37j_G^ys5sGcZmzjmHx%OP(s3JoO8$dSGzC|aAc2e@~^w^ z+zv=+5EBwDAU>_%`l7ESd?#SR3-WTu^vO+4n&I5s?o6Xx`L2cLjHR6A_IEgT*YR0K zS4)esM2FZV$~d_nVc}JvOTLp=83WT9gsuL7H1SP_&__c$b?khMOn}b5_Ws;z7pkLZ zflP#iSYizkD7N_*v&H`-n8g2a_2`19gNR=Gh0w7kMY|iOcYttP9u@1MU%%-Pxsm&;t-_y5a=zpojVBCmIzMu$>~xR=urQ-ST3J zHR@pYyH7L_jFk2L*-CyKS|^=t#nRA>BtM3n-eW^pL&!m$B2F?kT6K2rcYG$mI-!)s zG_Jas2!=Y~CHSp`w=(jDDC*Ugza7aUgUo<*ND^3y;RZZtMF&W#02oJrS7}vKqJd6$ zHwv8Jhtwk}-<`%nX=wtFnQvxKAT%iJVhdOz)P#dm?hBrq=Q5p(DGP@hgpp>fDtOJf011>Dz* z3tN7&khr6sGFJVZeCwL}iYx18&I$6T&B@%6sFvj)vTaDoHfLWM!p2^siMmaa{JEl> zj}gKA`$YRLe;63p3quz~KrGy~18-Qm>WaL6@4axsk{-%hL6Zd5Gja5{Bo_IVW=jtF zvda8&+jF<)cd(fKAZ#&~NM$BLiDHQu@mF9Q3gE%6LOh*!v|sWIp|Vzl0MHjy!Y?KF z8poN>Sl7F}Qg1=A)@dwOo^1v@NQ zR}Q?O+n)}K|7pBKjEX2!u)YMq%`vguq8X1r9rcRf4;s4GDrIY-BcXbw&`=Y4uEZGq zVL-T~d)+iTsQgWD2HmmU#?*JqA&0F5a}R4xW;O9^y3jC|6JYvl;R00LNi?Bv1s2$M zZb0VTj)cQZ_pA$DVX^XvoWyeUhT?1f^#Y%*SsK1ao`NxMGC1ga6 z(_VWCX;PL+2lO5<(FTK8R37naAEPgq+!|C(8dI%1WEpW7x2GGh z;8fQ}&2DvVi8^gi*g_qnt-MyXSYM;qm>+g4XO6TMd%2*uDkt{_>t4Q6Dw9BOm9$3Y{owx?I zR4*+A^Ap4!<77LRKl)EJynhicYA!l@87sl-|1YoQUwxAZV6}X`m=Xu7S9^e8bV!lk z#c}jA==AHuj54il#!29_3-5p4d-%_miTVFatN2~?HN@-6fO#bt3EwI2IrzqYxttEa zr1UixVe>#!uZ@98Wy@fAMy|Tgy(%E^i4fnl43puL8{7~iW@>(B@b&laVT`Mum9`V= z|61#+-4LiOUw>OZ@N~X_B~M*4P+N^WymPfy$VGP3?3B&%8-!B<#bfhTN`*~1lt$T2 z!hmCE;}5vwxEwO&D}v{~N5)i$$R!N zDvBPr!U1skV~**O=#^ud!e93Pnz{JI`N;a_41%g=;!__J)El{UFN%o_LZ# zQ3b6sKjU^2@XYVWcbW<4?kQ_=lZVMis+3<~4g_+b@jS z#W|3|XMUmP(_!R!@>9_2*Wn2};&$-us1cem?+;{x6m&TT0JGB_%j6B}LvJ+oDrN^u z>RCTQGXkghqD6cR>2^{+|A?sch!!(Ps|K%XnnTU|sULi9w6s7t1533)?BfG50Z9Hg zn%Q5DIe^D7{TG7BNc>e@AlB$WEC;ex2~7-o4TzD7vZ(sVCDh8FwYcITJGWOL+h{0d z7&SjVp{xSwNck(L7FuXcDMW!lssS9hS52rb(Co3_!2ymTuP;Lfg=i`8LUYOhIg6_* zY3Dt1Ez=p?YNt0ZgF_(W%D{EQsNz(6ZnA1OY`4Cp0G&<+8M~-=XQoLfXnJ@G=tbv1 z!2xh&FE-`pgTY`&-*E$zil38_#IMRcKJTG2u|OXXAJmmHJ+bTo?&(P(P~ul#@d;Mo zE4mwcyQIGNYvo$r)cFl(p&jg74>6((QkK%uN){{{m!kIak=v=SH_yx=ULe7f%P1;e zcq4Z3lt|HQP@~&2I&ewr9!Z6DT^$=0gH^RiXEbYsD>&PO>dg})3A+TaPjv|n@sEHSKBY**q-GYl zkc{f-zBWas84|^1Z?&a_uYdeqizh+tfPe7fY3MJG}7Xly*kyM%K zY#|XU_x^4s)?ZBRXq^EU?*UN_Z4|5H#1rn`p2@E7J>edcAULA0go3E)&uF;h2?p~h~ z>C_Yg^I`bQZJwVsh4Lq=W1^!=KeYWn8+;j5g!UZpZ{JNEgC!Q9mNt$0_@% z8M(zjp}%|oKC=SREES#zJI}#&j(F`X;(6sPUgY^(FS2=Z@W8+JsGcU|0{%p1_`Ncc zHg($J%y+P%tj27F!A2dMp{R#o(UXDLfizruF)o&)8J43MaAc2}cC!?J{ocLwAT{o! zh<~@Q_+LF6-}hfW8~>mAHT=5*0kf??)jQzAN5pHusnZyrywDKn!y>UPEzYFLe_uQx z((aq*M8drAsrSdPSJ=UNpSm$JpkYnJu;2}tzi58d>YI@ehgbVc~NV%W-`(Jbcl ze$zp`t0<@-S{_k|6i&fFE`W`#jS+w^cG(O>b0Y5XI!ZkvSBLGZqW<||=mK+npp1lF z(1J6Bs*eTK5Srk%-ha6kWFp>mo)ZH@J1~ek`J2vQi>8N;LH1;%9>B#9;-QN=6o1MX z7L1PGEQg?y?s50mWbaK18c)9xUE4a zeD}hED751|33hOyAE~u)co79Oi{XCRSu`rQf*^)2kVSay<=>7HF|>g5q&+Gbgt%&I zQ*R-`Bk=8;IqOg<*Z~_7hXJhWz}+Sn3#bbH5~4EM`k*?CA>lV$tD9X@}tkt=@Xb?#s!iGHH;Rp-GC(;fy>yyy|sHK%0lG@K><=0 z00m4Ezd-i1CIVouU9bqAM>F|NH(2X*poON{Vab33tr;9RU5pF^cSi7bU^u6P3LLo7 zL5p$xFZ+Affgs6UP<3er~(dsknc|(RiJ%GZ%cg!n@C#2fF_9d_}g)C{stj3bX05S z3$mw(_5@rXiiUQAE>}V`!1-AQ(AzSfY1V%xn58)fk=h&%P9XbC2~@)$zyx@E&#B82it&+I8{bQ=jSkF0N$Kc=x-@v2<|2lLz2b$JS*b}0%*dmjZt#^vS#X3={KmnR#P?9wA z&m%}y=%)p3V>%%ce{K*9#l5{I$%F(rWk8Q;;kHLHi6Id*!ARpBFlO_h)R?6luj(VA zhxTc%Lf*)zH{gX%D`wCIK8$GGfEQwT={9749MUzn0VA=47p_t5f730(k)ojRBfR`K zT@dKbd_y=1dH<%nyaX<35C-VN6EQntPm$lNcCchG1yFZ-o6yOGofDfUg|dh}pl7F z_ylY*$q>+E1N8Y+Kw_+i4v3FoLJ_T}9#K#^zv&*K+8@yja-%TI&-$TDoX{L-GTIA9 zQcI=kKrb~Q1r-D9SVV1++Fz~rpHn&y@moelOBVTIM5~aWzb!USD!;3B$Oi$?)cMe zu;lX_P;guUThN`Iro|z$XG!RGdZ*2yh~IRt50O9?BTAV}zE0BuZ!N!xdX1_zOe$#C zDg~U>Avcu?;0Rc7dhm7y|H%k-?P0ZmhX&)=&%d7#Pt*QEX+vg1@{yDRF`)=-VmbP+ z3;5gRLeFV0k$tFv{NHppW;@_J=6#r@Q!L>05u#)=jD&y?)&ES6onMH*^RZ|9JCq0> z&4qB8E)X$MO_a9Zbl})10Ifs8knV@Am|1=66L~ef`?=x+JGA4=#aNlr_b#s`l0Rzh zm)kinmG{oHU1F?86cW&c6f`-?*s=U&FZgc1QQ(zs8`NG+c_<&p)+>gM-gi4zIxmH^<8mD_cV|C0K1w$2)PMz;ZYOWGJ zgi`6+di(+aL-4~!ef3K0AA;U`x?L#Q8}Q}bPCjF`6f4WlJ0}w3v*CrcBfMEPhkONP zN(mWGkDWBuY5WJEGa$4Gi&Kov1kSa*ak}yJzV)kXCT|OBAm!_Joqi)}19Lc$z_~qd zQ$8gTPv^IcgbgKlI2`<@0cDU1fE?1;YBLWgnwuNF-4_Y=ff$LKl+)DB?6&|{I+~%^`^lq5F!->yAVsPUQ43P-fM0kWqxykwBcHA40g7KepYlhY2Z5Syt}Rd&$l^eR^Vrn zhFThTy`bM*7Tc81P;sbKrf(Vf)bWc9&Q%YC7Gj^V^bMe*9{k~V#5=DnfvCM4O!c(P zFmwu2VK`0O-sn#pJ@B!@Rw9L+DaAK8miPVOnQcR!CZ2FUWcGA&_Up;Nz0Esl$_#!U zoq!RaAL{RRhd(osD!+v|u&GWyU5}}KQ|K94vD=+Hn$g|zRbuP@;Nv;h#u;9;)zWmz ze!w6iv5U{TEC@Cv#jM=rsd9W`ORYjMH0JDaZOxCoC z-6w5TL~ic#__j8?KUaU%vc`M5{Hc!In>ios-Qm3NuW=u~DgLzmU#RE&lf>ttKg|zJ zzFu=mgKkO=V3zsDmHmf)(>a5iVWuzKb-)JkZhsMyIr`O=HxvYHlj+IoICz3I@^k&P zcLL>|_#F%zDSAw{b>U~-HR>k`^HFMYs;MZ?-9x;}2K4<;S5_irh5|m7w05#lvLiDl z8alz36g2I4U7*vyW%M0rhYcAfC(C*jWJXpwjuUrqGgp)*K^Hp8Stw5^0bhs&^W!o* z=q}T9G>CM3s$L&4gt_k{%uqnzC?=1o{Xt3;-KCjb$YeD6|_51#@hZK;@m6k9dm5K-bIGVYwtV!FsZfT+Scp_@!4J?!z3uzO>ng0#gnqM9 z$PR*QwX@oFIV%jUOl<60eK!MQXNc9_&=4Y5RFN#7&e^U44e?X~b1RaF{*>hrv6)Yfn zSQ^_U5s!KY z?JB=a?5awfdco&D#4_Y$yyIkfVYbUZXyyz>ZGfAPzjCyj*C0EwC4sn)>YhY~KCDLh zH3*aI$XPTao&&$(MM5t@S2G6vWCu71(6(Q~K5*XaLcQ9>l0rhJr>7gM@V|H>tcuAO zDvVN_BpyuveY*l})j#3zD>(g~319OUG-YCIqbmqW^nVO~qKCzRJlF~z+K>oRSeMKE z)Tf>dSycReoPT&@K-&S359~?11XAL*QSPF;6J!`s*3lRiSe(5S`Z(^;$A@?*;#uP9Hren$XFdL5TDTgr`v!8Z74+<8j}s`#uNIY(KyfluHMOOC zm9U|XT~`I`Vjz@Zu6+kcU(Yg{dBJ(ze5o8&Z&&re73t_sQOWxLecE zhFp>mnFC=8BwTkp$9-?$PT7EkH=DTJN0&3$cTx&|8Cr)=t5eS!+c+?kga=JJ znuS3FlmOmPVKTTcl_Q=2(V6}4s7!ebH6@Ojk1=e9Q}rhys}C}A1;!ha0g(zwjtO=f z6*Q?iv{cXO&_?pKvVA7=&(jjc7_b;O2?wsvfuQ|$Fv>pv>_Dtaxf=O%dQZtJagn8t ztTCtXZ=@XmW5)P@WS@|~2mWtySRPkZ#Vi|CRO*x3ez23+&3RJMa7o0t1)1(7TA?q%y zBNl+Nx!)#C{o!i8Ms`as6A~&5iAsF4+d09Xy^GF=fAjCDeXjx|{Q%yjL=Nq`dtb($ zZ{cg0CCn3N?CKP!c~oBmiE>!8Rl_~xKj6r#{)Qu;*j4|dW10zWT`&8N?KQrlOb!jJ zS2fgE$8fOQm|x~oyJ7aUM(oN7#k;H0f;pim>&w=HIlh--?|xqyNN+r)psawqT%Zik z7A2!7Guqj$2{a2z&R}=`xyQrLx4qQFxM@PkuStBolQyu&p$f=#?+;Vlp}d zS}kfv+rR=9j&$xJN(Zz1(uhILjh~%>R(wap4VA1Fn!}qx)z>y%)Hvq0lp{;>67*y7 zQgZ#s%r!oVCdJ00^=qha?@bd)2#!@tOub?%*`MZ|ut(a^c9I4V+jc3E=BIab&NXwr zRc3CV#~7;QgGDD%ysB%9@UlT?rTO515?~3I#VpL6g#A30 zc^p1h?=(P6R&PftdgYp#+HYG`mHH@<0Y!!Bk<^0utuxAruvuK-(z-X;6)MJL0&WLQ zlJBt1Fe|H#Ig$H1s{M6I2?K0OTqCY$E8oStKjP%%^W7KW*(tuaj=gnfFdX*Fn(yii zvg#GIdJBaPbUA_s^BmYK$DW~q0x}MsJxF`&CHQ`s!Lh^a_}%nngjm98GSu=LF=B}X zuMc5KvuhmcAB{??cLDnW?8Be+Iw{uVJzJD-wh|uKG~ z(0ajq5eD{02ET|RgeoF{(ojViqY5v3Z;iL_h!r^Jex0^mJ_sx?M6}XIYq~}<_~Pt5 zYld^`@P4$Q+uou)W&&Ufq>9-_eNsaHf}cLiO~8>}X?4N8*HGQa75wKB#YW;$b|3zc z_z5PVE$jB?mf$%>aldSkizAyqM-Vo~3K4@+lnY(2u}v#AeDc|}g3I6(U1e*a}U}Jq#MOL3z%RjK{HE6pzniV~FNBBv0 zXz&_rbf#ie^JAxjQz;E~9wsV2S%PuqhQyjVc8-T}R$<2wscv7UR6pDHN>(MF`zn4f zYsQvm>y%QvWH*ct?Di|puK7`M(%{8Q8|A4!up^#g&HOlr8%tNQcwu;H(N>Ej`&O32 zW{CA^zVyX{fk%YWmeocP@pA)n1?yM%7etXl&U~HW$LHdGgQf~WdY*unYp45dJ7~O_ z#l=_eLj_~FlhRx4a-JOBEFzQ+WR48mzT7oox7o7&>rd$A8;UFA7x$b;I!)~R8})8T z3Li!=8HRjntccG{;2)4rVXcC{kl*2KwQLg6zZLa~`RuX){dx7&Ri|s9-y$?>Z0qb5 zOLl$Abx)tJ%Mrz03% zj|xxZPw*6%zY)40HzT-GEPOmN>tqxExhO9#r== z)!Px$^cfZ$L=A{E$1m&4tb@zQbaX6eHDiaRdZr|X=oh^AUb74+n`J%K^`f6ucQ!`GK&VzSn%A0`-wMve>&c&ix4sI=GFtjruj3STQdo%vr3%*(tSVB7N!?~b*Am9>>QE20)fF-BSPu2W3S zS<%yODeTv;obBkaQQ>}nVo}ZZM`2U&A%>jLf|N!IOTxRV4WtWln+x1KWGuxNyQ<1R z%F+yP&OTeKGlQUeoAj0QB4|slI@JEx#0;;*e|Kd6m;AU12zea> zsQOO-rhAu@4c1L}N4NQ^4kKi!Of!cWS*qJC*gJ{X-clM zviZc$j(Dsk$-c%(et3RT=;I_#5PcNk0DdxdN0t}SaU}-pxdt`bjjx*t{-6Lg+IK@i zXr%km0GiBrI16h2x3uTc?0+#knGX22dx@46PilMliGPjNnV+BveOr}3}1($V#SqvdpTbb2GF z$$Y(QA}PRrGD{SF6z`9&56A8^Ad^o2Z%S}JRw@M4Rms9FGD+n)1>iDmsi<%^F83h& zM{aLyq^5fG0}hhHmrcUPg9~Rt=FH<$(DMoAf0Q0vud<|GQxASC z-w1|rX=Qa)q@1vMOh?1{J@?03oRbWLPZIlr(Oj{YrIyEcx|_z5!#TE=rrVf+S5U3W zwcD3DW?3Q>ORUdieziUDn<2mVslF0zci(W1E;N)?*TL&`yVRI~$*`37nS7`hcBI?Kdh}MC#>-LAAVwD>L>L(IDoI7#Vf9sm*{D^4) z??c~L<9FW7yLHC)u(Sx>&*Ws}0YLCw&NIX-+P%eo-c!RkXVdZgYmWWe@9#}S!Q`Gi zyt90Q(ayOmyzWt1Nyd?IR>Dt~G1&PiH+j#sCd3=4&JvsmpSu`OnVfH>v{Pc-#6LSo zjJ0<5b_Cy;zR)Nc?~@5QKN@Q6T~(A1H&c!!n6mh}F}6o$-9H^Y+d`ta`SSlo9^(*0 zdmVNN^7)YY76-)c@sTMnXxDE#-*unAbWo4BAA-jbVq{{G5o>`BM6J=6wJBmMqNnX8 z5_I{aKWNZ7)bKg%);iPkD@vLs^Up-e#b~k#Jobrf+E5%9ytRZXaPion2DjA*0btEh zjxqb$1OonpFS_vO+pW;cj$7gomi(g-?WpLx?WQa0h4z;-dw0uE{*-;G5X9^=Bh5ca z)@TYcP~wIpj!^c8%eC+~?PQD@iZasI((tDXhQb2_gQ}HO)@8cSD|4DBf2i@l-`mZ= zfKmq~4q_p3G($>b&zp2u2N!Zs)Y0*w3#M2xEwS(B1C3P%8lAP_8pLwC&mz1;Ekt1* z2D@#VYh#-kda2o{Yb(&@O!jW#!o_*9c*Oz$?0nv&(obbJTUq8Sr`2!ZhThguL|5N` z6)p{R&vEB19QAx{%b&oS&&Mt89j0(zXWTI7gZRlKjg!<)37RvGq>m+w`e1GWB_lS* zt~Vqfv?$r0m{XO#^yNlR#RDJzO=80he40i8KSJpL{(OA)0`0Z z7t0WV<)lsz_pK6Gp=h$h6|Ty)ZmV4d* z4^`nKM)Eh^RZ1!mDWnM$0BTCd-ZRwL%!(~(v6*NYc*ngtrJ2q6Q^h#r>6!l3SDc#& z3+)P~q7P?$_`tTyBg=21(i9&$F@YbVBS|N0VMDqxfH)2>90}vhVLgaZ-zvDoP*Pg? zJ-y&z-=R_#wgCSl>dCZFGVkQT^x`e7$g)YOAAJEpPbwzK@6H;LDM)y2ZFPdF!h<{g z!G-?Oym}*yh1ZN9&%k~Pw@!giosG~drfKwY3bxwyR*@} z_yb9gQvOrJsofp#3U=e=c|$`T2CceAscF6ve7EIR1rdTKzUiMAa{CYL@U^rZK}rJ! zi~-Z$f-PIYJ|Xdv$Xj>Pr~)wc5T#?^u3ytl4{OA+=4#j>Q2p@oe>L}sz=)^D3Zu>EE!UYi$p(Gdnt;$_W$9=6 zls^TB-P;zq!6KR!wWMjgwW#ofUm8Oyz2JGc0+XPW()7m5Ms+f8K*|2W-we zo+kU|t@AnpX)S;hu_MHw(`BI3T1qD+*X|lRALV|sI_G`nUe>s{{+$a)PGx<3|Q_TV^`% zuVBcreEKAG3`k46;l%`FuVOlqvKo>bR}!DkrLXRNmMy)O#96V6(hAa!vS{LxvUc$z zamVh98ri%Elsoa=2WTi$0U_p)dB%iHu&Iaa!BD0Q-3x@}IrR%?vFBL3-WFdOHQZxHFGc!Zom}qNY-0AAZ7`vK{PNQh&Lsd1I6j#*8!gel)#d zy#IyM4Kh-v42B{nR(<(dh?11b+BuamtUHx!r&i;HXA+=nNhze%)l+)N%$WGE+aO-w0lRP(U$6>P$RQv&*tC}+rN|3rK zAmyif<6wDc%j{vr1?J0XUu~XnZ5eavZXJzZb;YTSBJ1Kjvxm+3w`N8_gz$LhuYPZh zvUN;D6wP1}l8AUcyoQuO-az(T&8Mz zXxP$~{VZJ4`qJk33|{;6Qvoc>jtGT}0NgZ}L=XU?Q%K83Q&rW|ipw#xVD3VO+UAy? zMP1tW!<$mlLEVj^#Q98cS8e|Oq}F?LyrZ+^s?bXhrY!{}^<%ujqhY!ZK0+npsuzh; z&uZR!8Qt}c@n&gg?^~Sa@JyByf&n1_%Yq#8=U(mE{>yQjT3ePEz7)K9wETVQBf-0N zbN$c~Tdp9Z?<;Wzvh+HbS|UTfFonnV&uvGWxxrogFp`S7kZ3UPE5&kS9KVy~a3#Vb z)vi>DRC`{#pe4Yz!rLL0udgpc%o@ibO~>Y2{qBrf?!}!+sQ2NsVRD1aN1?i+x-i?oKY_y>ML@>-0YQ1cf63V(cddxa(Ly*k!!l3)C*G8;6f7xowa6j z-oO9yX0flAQ4&x*zquUHWU;?=fTjcdRq9EN*>3Y|R?r8#-H!te*VSFN4o86Q=M{Qr3Mc#F7hFiyKj^I;y`jC>y%k%NR-xM3z*dv|< ztaYQ$i?vL2Jk13~?=JB1i*LCnTE$Lp(#bhXK;sZJF5?j?X#OmDBNfbcz(N0YD!ZcZGrL%;}7yABM{5tReSm*Iu9&-!(@WJil2LzL3Ptq^G z$H)3Um2Vb#LtlWHGx5yL_3G+?!**|8cIbIV7Qgy+s4VRs%~*@ZQPp>*=ITpzrIoQJ zPp14#MWQ7Hs_B{HFn)`nxU5{giFI}({-j?i*bnu3R!jf%_8>4w1;Gg1Ko%f1hgSsT zow^_$!F^L2<}n)q)z{fdu#awVp!OW&Bu_EwC~B*mUsG=T@#VW4mtWrbsw<4*rYA^y zLXSRUWB3H2KGRM&0q?^u@9f+}$tP5k@%G2p5O%l(zIp0j?k9KnOax;Z+zyOrbB@;5KOZ1$Y0 zfe2&XcpcdQ>dJ!7#Ch*QBg5V}sFT#mMexmrqL^Cg+?)Di30tEYT@MDi7;HxCFD%0> zWpB-`()yG+P)8Ii&qB}eHZslyYcb^Z8zA7Wv*<1)&Sayb0Rg|c%)D~fK->QH@nhdg zE=eiex)jJ8ynYQPG?t!z^NebwN#yfA6jsJ4zd!BVG?Z}!o(u&pNuq$De(00#vU2F` zZRJG;ZT0e`;ZGCA`?8KQqoIW_ajhis2Ro^$q|y*7tt$EJC1^EL%GY;m)$17#eqm$6wEq(car zYd6SazVN{c?x5D&Bf(YiT(P5ujm=-p=P&Yf0_R`MC(p0v8cGm5Fn$y2K-?wGAS@7` z)n7Y`dD8;ktMM4Jeeu^rpJr4{oMf3!LIk_EPZWl6`^VgD1{@ zabN*CwdzSk>Jh*BkyVF@&5KUCs;AsODt|t0sp~!PPN(o;xjWk0N|BNG4DGD)NQR*5 zquh*EsRh+-$1OMrq-bkH-t5ApDCP=31FWd;GjDeOT$Q^)hS+jAMy#othS?r^l&D3P zT1=fgWWnSqF@+TN?t|K{A}ciKS&}slnVbO|+^DF#bMSK#=3wt)m3&Wqc~Lh`-Oy2V zqKcv6%xL-uZ*-W+do_!}m-N;S0k4={Z;tU^b-fcKQ_F}TIv*fOGHq38(%0hc^12wt zgNC7OsZS5t^~%UeXoIs&NNvySBf3Tsiiqw$9Em7n!g=-#)e&ygrt3J{KcjdI?p556 zpW7EROKA0bKyo<6&yX^FF4ZPXf-Sh@*GapWyZx?>&YYbO+uvqd1tqF$-99PRz9(Jf z2$jZMDRiqrdKK85FiD=wxAT*`;Z4!i!-pM#^Q=jzlc{Nfh&*J&$Zxum$%%)a2R1Lh#^PP{2hldbRg?^Ea6rBWzxbQ30ksn}^=tYds9yOe=rfIjqH*;NATv!A zM3m?)JY7p1WO1gR>8}8=Guyn#N2w%hk{0YY9Sfvj*{E{2O;9`8sviE>h_U!m{rikh zq3SBh0Ew@Ab$|1f1~-6n@uMs?x=v&B|gZMQx z*p9~`wX0UJ7;q!1$+){m=YA}uz!%AZ>S4%HeMZ*tXx{(E-g^f%8Fu@kC@NMEQIQ%I z6a@s4UL%53>C#I?dhcK;iHg!C6s1E%K$;Ngov8HQL248Tp_c>#sh-#G+imupbLPzK zJ9F>3cmL%m0+V;G_gT+c>sJ^!7AQg`a&f-j6~AHO1M;lfG*3d+gQLXzDF=s2X9>5H z$xNo`;f=m^Q@>f$uF-@7`1wW2Yt46idD;<)h1y995BTcy8?@Qy0i4_$2!@nQ(*{ie z(r2B79)M1O^ZTcPavEAzVJ{3fB)Km4Iaf&H;+(dZ3kUeTz8co};i}+C%Z_N-0b*;d z#h20d4aXnye3RRhL6K>Y|U%XT<9Q3_>ASg=a-}|etzolr*VxkJej|jAg3@N zKMzfZ*;hDS+i|g3cxDE6kX1}i>kL&q#|=F6Z2YE@4d4y{19mH|W~fK6>h78@fwd#R zx^@)J!fOE!%4$219Mf* z{Hk+lt8?}*GVZ_0-HVH%_?8=O#=l4#x-uS(ejr$T2uo2+7E@ES@mj$E>=ap-${ru= zbXm;{Z869~uy{84Yf7{cAg0I?I_28(eu&ZgCWI60iE%@uR<0;z(~0b*bX!0c<6IvE zUsAJS`gP1c!ueQZ&29AvI}_t1tzrYi%O6Xoo}Z1Efd-JvL`3`gy<_-%S^%$XG?nJRyf;m z5n?&l@xava44YOB?~MebwY|2@R-+3VQOn9qSa_~t`ppNXVYz6W(7jQXeoGSHK*sa){ID^UwSQ(1%t2O2_H5pj(?? z0@y^Fb8f7_yWs;E8P_1*=TrNibBNf!D#@(^1_1|y4foQKhdM7lwucvuYv@oIYR%wtz~3Bp}FzE1kJsD?382 z`d2NDqb%pDf*q8FIRzem^TiIwn8GZ#8n*_2T>eZj55qO)*j97;Ec@dD4YybjcX4!06z_* zz>uRGc?gk&pP+n&3_XQ;H<(BGP^;ULk8Dd_L&F))j}C8Bf1mxxQu*;k&KFJom7)z@ zt0gI&f!BfCs9|oeYrUbqJ1irR!JS?gu#&`b%gm>6 z+Ur6w8a}I-5@N`jbN50yI>T$8oV{J8L;84LZ#^{9fn-fWlK4v7a6IDLZjsf@VcK5% zY3XN2+M_vGIwOg%_lqc!++XCSO{bGN?6}Hz^a)?3QOTv8?u{-!$NCoc0Jb=ZU_ou4 z0P8`^Ms^Hu)p6f6d;RIs!%we_40S9DgH2u@E1q(zbQ9=G&NdbF@pDWu^0hUO81GR) zu4qz`WovZj3Ocb9AmRg#Yesu_i4G-5yL3(+<+0^><>Bz7!>W#irG$i4iaZ?{OZ0tp zvj~hN739J23(k`>nwP_h3Lqw@W^1>>)8{v6rDJi45uX&|F^tV{U_5{E?UMm5YkoPaJc+*1ZA|fd1 z=mccvkP4x0Whe^_270i&tHInqgrF_jZ^x3%?UG&!+rBjVuAcqCmqbsnFHen-n$v=j?-BbJVFJ1;A7jMd}<@7$TXkfCcB7wNN3K z!iR+?d(}rd3+0EL(D1yTIKc5PbcsB_5O*;8k{y8J^VCe~K)ofTyPeQ!YsK{Eix1WFk$q zg|Ljmrt-!de!ZmnLoqAtD~0K32~n^Hsr3M7%-`XOJi%&OsV2qc(LI6K5*s|MqKGm_ zD9F4GLM|#1j?O!Yi+CvvgkM$0BE>OKHL{|Y>i)@P%TB^8q61)Zt0?UTaPUqD|J!#?b)|-&SKa^aveu8#`)>i< z#ZzEf`6xql1zwrD0pYdY2D;ozDli!-1qK?USC9Y$ly=q`olftCl!gBHul@h+L;ec9 zL}oBoHUpFqJg}Ij{=@M1>xb~+ zDY`3s;tvBo>+d&%S4|&Nhls!xD&}8u4n-XYa_$cUO=cQC!3{80|E4;Cf4(TkSoZ~Y#=vKGy@>tSO4Zad{29+ zuLZL&32;M^2XH{-j!TrBhag`Wfs51L15HEfKVGK){@nkciuZ5djVVCJDWw5WIJw_< z@Xpe(_G{8QOfV-;jsLCQ<+HJ>?@WIij28N8?(H0jt=%Z-`rH-wR6X`l5AIv=bU=14 zpP<0d{)6+oQ&#^8NKZtPxNijOxPD}Tg0E|*=CZ#R zN0R#b3hN1b5h}aiZ9OD?G zk&IrMuKiSK{c;WJnnAGm@RGrE>t10nT$&BEuAD+Kic^28v3`sOH1IB+l_B3kcBm_+)K6paBb`#~* zE+xkRc$9Ud?|INW5UBXzgL^G+sjrV9tDT$?L-ByCbi-B)bQuJv;G z>dJJLgEeg84i#L}i*!`Ey(>vXbafCSSJan*Mq6Y*6b-BOBsP(ONpg!avJ!94J3*oi~ra3}C8WZeph=7ds5 zZPcIl4-`I4($N&y;L)`M*||^m(7WgglOZ?%FvM=sP!Fj<*~)s3#H0I7=$^HNGmU0R zX4pD%>gQXU7vpcWI2Lfe8{WoDgeWF%F*l^o=e1OK%A&9F;V5eB=72mD8&3% z5ISPb>*Yy)N0CtgR3IwH89%03471wMmVfWCKbfG<4O5BBCaOKdrtrC(n#PXft-5Zk<8`bHfzj&XU&BY*~9Yv7=^d123MM_J`d1X`H2iIwlGV!!9pag*=H0?zDbHiemd z?+=n1%^#6jM{%7p+6QzA|8|Zm7Z9)QMA&Q(hp5Xn@6apK2>|jp`xeuktI{diCPE2U z-XFbxFGw-2swc)UntzV?tSCqur5R4o2fk5rx4TY-Y}sK55evrgcO?=19vUa=YGT*D zyXTKx*AzFcyK)8{&Yd^SbLW&fw)-q7w6&M?b@PkWN*JaLk3cprfwP)Nib(C^d~@>> zUlTO!A4^0rj$hHwTOEX0m&(PB_AR(WnUU8w#Ibv~9ahNaw5cW3DeBIcyJzT7NSkI< zb#0}qr^?slDB+T*QOSoVp~E~!iM@qku~m{Sg$%wRjX59als7t{VPwp4{8fA4nmcfP z@@{d@lU{Hm@SE)3P@o9~i(a~u-@_ks8LudV%+{UuCaS!#dGeCw23eDKA+OR6s<{dx zBu`$=2*P@%0@lT}=e;wFK+_s4M0j^SKz+H1SGz^6v&kc!KKkhXNT-<8u_&fygHM5_S9v*5L}@GsEig zjXLduk&O^-&;_!b4^Qp(&u$tM>GT zZicpfxqm7ESe1snRRW&jBieKsQTp0JUwPY(59KD<;85u{L9I-x(R%K5g(O!@ z7Wdj*utOMMl=}%5qI~nE$c4(PX9&=J9a+j?&aP4ug~bP#QISF~I<;qH_T2cvrH3cC zjzRU>wpl)caSzG|6S037L`fDuDy9`irBD7eoRL&z`pLAGiE%6Zy%-_ZJ4Ct2K$+W~ zP!Nk#Uqt3WzspIl%Db_-0WRu>Ixn=fPu%tB&X}-meX7@R9FZrFzP7wss(3Q=GXsSO z1G<_D?_7(dE{XA4P|K&9r(Ea<(W2#y0l*@CYy2bmw7^=QVis*M9?Ap;N~AVVdLTUS zOe%VlWw7V--xK*~b9_g7+W6n|xE*&~CsQOUGbEL|WK*LQONz`7Gmp})O&WFJ;ow)P zAl)}16%9;PHN-1Ebt?dg_N^TpB*{)2La+hS4e99x#@!3O>y?&(g54 z5%di(RVAb<&_)33w^#7Nd#;moC_b=(q**4-|Bhdbapv4d6`;TxYSn~VIR$J^8kBrj zl%Q_Ri;f2Y6Qsd}KE^ouvCwENsBfbsXs{NOYU*sVw6W#pf6}$|9LNlDU~GmHDj3!l z`S?uXsEDeB`pRw^dn`qlMGjoBj{~kSnR(>SWKvL}!Lw?_M)If4+%)gE&Qjb@#Yp!D z5i?u*^}i4|8Yq$7kb$4Xa_e>`9YC6<2Y}sIgMsF$zlGCF0BW=DwcBuf!6@LmrTwwC zU6UI~yGJJXfmDB|Qo6Y*H{dBA%b~#ij;45k!Tb2{_GKuDVR3zX+rc^MKn2t()z%x6 zJ19ecH#!IjLN3jEMSq$tr@?zL9ywsU&#>ZG+b8}ov^R)thL0n+Pqv68za4!>=-FO0m4j+A@!<9_4G!B3bS=7Y}ts z$W&;FNe^wqo;al{^!;O~1jz?|s3W)_6Y35p-3?!C9vH?+32JKyDt5Sv4~IN(Bv6T7hqeRaZq z4z5mD7?;0UcZmXa6{7n=p1iA`XEO6vs^TWhrf?ZsUupE3m%_Lrxl?Opx=!4h>?R?8 z=1j$ZLs5bF_Z-WI_ba87J9&X6{9j&mBVx~X*A7B>gWL&9gD;&dq-s6sBucL%>tQLa z-8j*3plguZkOrpr2Z~<$&k1w$1AJ^V<<3lBFEa!(%IY}UWeOLH*r%FiIQsG*wiwZU zGEI@1)b>%6>8SXf$=Y=FExz`4M!bUwS=?!J#R&1wi@P;o0E=yV4{cE=wDko}VX}iw zkT+2UB{~J^9ZJJ4Cv+egpWU0>bZ^bDA_#G!IEc5eWZL&ZrZA;E>J~Mzp1KrrlJ>xV z!;k_HFDhGaM!S6nbfeV& zFzn#|Ff@44vK*6Xr{J~lia!hp83=$c9;JZYCKZ4>16weoW}xwo#ZaEc=SYcbwjzYo!4vx6-57?DGz#tCVsIh zDn=Nle^We~ZTDlJmi1m+hUdfQB3gST;{c+;LzwrFLh1v>fj0IOHIdEW6gxw`ejHLu zO|9?a?eVWd`v746NwyK5(w}jqbC+ZL6rIgd@GHq9d#8%GMM{I$1opFOaNxi$;qR4tU?eQzgzjzs!he#R{ND`t3 z0Ew4o+yfm}(7#gVgu(iUkv}1XO!!VvD*CT-gO>@~NJ-TcoBd3PxFetT-{Tx0?&6Z4vn{e3k)v_xVSg}?z_tD6~o6+^Z z|F3D}%kX}L=sXlMz*!qxlpAk`x_uK}9oLZlhDjH=JTU(8rkrx>jxL_r!%!| zfB}k`dE=A<#i`_BoQFhp%HpDyyR6#Cr>O$-Oxw9ryRtPzrzgJas*!i5!Ga*S57YJi zm5g(FK$oId*7k+|Y@y5b`)KdAduMoL1@X4~;upidcT;rI>?b%^8K|KnGe(Qup|xQk z;Qxo8n5!&gO7Us44 z_)a`FFznZ1U~CYOVK^hfbNVWc52!BbWBH?C!RoTxOO#pj>LU=%`BwlqYUmLW!O@i$ zr>DY-KZzl}dExzPn}Xz_Ltwg4^q__Rf>*1COR+S&-D~(i5p8>)zKt>O2BJ-RFZ| z&W|h$@*57Bq)AsdX30Y?(i6~icEnn{E$)O37%m+fyH`Rx*S*q{y zc`hbCatR^pp!@5_qX?xxXhMhzc+Yj%D!zo!fJds|< z9p@m(_guz~oOQ;HpgID6Mtf2U+!+Xdgk*x~Qvh=Ubuv?{XVnyMu1$&M6l9sPJyyu~ z*t&Iu=hTvr@=PPm{YY#mxMc}=6n?uN-%EzlcH3#;2lqkJP@|!RFv18vG9!lzEfuU4 zd6=?S_&G8C)ZU(T0=__YtoGS@bz`_QTUK z1cXHqK6iXUg!Qr9_r9qb`vjAy%Cb`jYIoQdjnpKVZYipjRto&yGx;_pGqR0N%+E^q zkBk8JP+_bjfN3OaR7$F|s=xBG?Ul_T zPv6=&C~q{eEoGpbLliFPM_doA52H;pHV`KcTKTxJ%m2;lxD(bX-5r=r5Bgk#)s|0P@`?!OG!85 z%Bkyh6oZ+cZ!{7%0*^{%4h=Vr$?PN*fU8E=Uq_|}35<{Xx4*Cj)zs~j>GdVO2ehhO zvT+U|?1l4Rd3}Du8xga0-xpl;R_><-fM!^g%)s~pG{55%=+L4S#ih+bLz!%PM}2HG9i7+o{Y$2Mv%U|DG11O}E4DIKRjJ^f8dvlVzuDb!xVxzE{7MPxlO zvq^b*=kTVKqenTnNNmcFZ?=ekKvr8cFC+@K6dfa@mN!_O9df==!`DHio=mqsaBsHY zkVRm!evF5bd}`qGfZ(_9J+2u^6UF7EQHnZ;`eRm+XPvZtkDtVse5aXmFn$C(g}q_$ zBLFsf1w3bpJxrIJ%`Te^i74KUm@r55h3+V((H2tqhlIfP);LG9Pd9~*!+rMleD^;y zjQCF~LjRM$Zh%SOMQ^Tx(?F>UJ|hYkyDMA8gwLN%)ADkqh?q+d5jy||_ zmD_)*&n-_gj2q_RRr2!WUwdQC{jPtA`*cW)2DpPv&M#z1as} zRrLpv(GYldS`|Bu$ANASb4bNT0!!$B`*+~(tZoiZ2c<*$n1MZE)GGJ@1|&zKm>oU7 z64;P~AD~ls{;s82hXGalus;kppLhMsPl5}}&jYJIzK_6?n@pjrb|A=debjDhFWn4S zkiSt^23Cp(ht%j;(0)KFDUtMn`W09Po{k5m@}?U*B(|&I)eTVsA3=y@3+&8Ud6?*^ zDGdI$FnnYZvZB6Xif;qde=Xb=>7`H9&dhP*H6en3a~zdykLP6PnC<<~Ygg&pOX zshK-p;dxpA`t0EQH*IWy&;Vm5YHTbSh_mm1jPoTx))@kTHkPd*W1xM%{}8y;RP;It z*u>skqyv}OfB%6%HvNTingZ3H#Lm9oMdQZ)O|*YWk6YLsaw`Pb9Mq#fgI96?A>g8- z@QJ^t{o@Xr7?6ds|DJ`>&=5Kbpf2G>MAr~x+5eDK+I^UVP&AOAKJX{-k-`6vC;$DK z{`Cd>e>_fTrDiPFIW(M*cK7-Q(FWhm`&>ysoX^ zs3u!gUe=5KioXxa9V5Pfp}`B_N}Cj{C;yYqT8kTAz*vWChq3V59G}cyYTSn zyTp}&H#exIA1@*%E;5luXm&eZtklV~++7Qx?BLYY14Z8b)r_(%BKf7K(woG}ZcT~H zhJvoaMkx1R51!@7dTU$^DGhpj=UN6|&?=m|6q&d}{e&MxkzV1(r9}NWd!N5I)F}I9 zV%wv0I>?d26!tzqVvsVu#kxs-Fp%lCfDmIP>jgC|tlmGmD4v5UCQX;QdX>3K2lp=~ zS7t(-UaREK&uJ(_nC&qf;80f3l5v;h? z==<@CLU9cdQY9c9uJBgX8e;g^1G|C^bWBV4$x%to?1JO2H~;p+K@`@5KW8jz-_f#o z_-p*Zk7n~%+vo7tk61Hu<|p3ielkSd_<97J^$D0(d-4Y1w+Scpc!@5M2;H2zXl$Cr zp2q@Lm)X;b`jA#Mtg zelCM<=p$6|6ZxrZO(z|V75Gljin%@&?Sa)uKU^fBl7_!J&w!sD9?B`0IlLcN*$2^m z^YjoJ)T)ZnXPyQ#*3+}ad#tK!RPiQa=C!VTR-W_f-4}P{wG?DtZr>olmyyf7>7=S$ zSI)lmq_$#<=7fThn{Q3UeBaI^ZW^TRJU$ikjh8e;l(uby#2YSNkG-<{GkG5F<1LYK zBZq&1hVg52(i5j!tUoZ9$2d1;ImYuPX@Fc~A|A<}WqWky1kXEW7khE%LYpE`6eUZ% z>&@gZDl#9PuwX}!LM_u&jHnovgKIQBUAOLbPvQ@`ZY%vudBI{=I>`sWM_#ky#;-%xY`8aWmKxzvLl zSgE6n^KBy*R)D;{3Swyy0PegBgbOKopWTot8L>Vgucr*koNZ+7E)I0fKPtr7bloND z8F2h~acc_x;wEC%ZrbR?H4uDNG#M=h7Y-Qe)6udPg4FqVmaDSc>g7Fv^$GbG^O!WJ z=5q8ABORAVo^;xIM&?q3)$hu(G}By`PmXaKGLN%mcKWbkp8-WKL1f&ksv-eN41#k{Oz z=TnWips$!wword?C_0nq%UC6r4Z$7}8yCxK`jD^%dYoE@fM{e$&?mSYfPXk(>DAGd zFS}-K@wb1gpH< z3RoBd?&(|#JEX`GXndb$O+(ALLNnJp++?iIc`?Dj#Eoz7>Px;B(~_8-D2inhdUv93 z>u-d-RK%qwcx_Ur9j;6Bm6gH=b*9&VCV3@3^HZOHZM0-fb`9-Ek(cK3ht>Ww7KvOp zDv~`@Y19d{NanGzWibJ+pO;!;vvn$PSzhgfcz|l9Djvx?oP8EGVdU7rlMw zOoV>tn-Z3{92yK6)Q1z1w>aL-Dh*{{ywv53Fq(t$2yGonZb&d)xHipW2DSPKUcTgt$14VW4K1Xw9Xxnv+4k-5aOx4M(>kan7+36Fdz@MRl46`UH-TW z9n{9r(HQg`g@)s<1!yQxmdk?hu_n*LWR~yyZe8iVo(M2rut%+);tfQv>k}@x&#BoV z1?2cY4D12ZqkBGCPJ8egS;7x#fSKIPYv`)}#WniC<>hsx;R?#fQ0}c(7v#Wq%bEUU z_&mJh9-`H*6DS^R}8UB_R93y^ssEx|DxfgI6pJ%Dy39E`7 zek49{OhoMwZE|gw!SNW@_OOnMO-)n4VK;PSNJ^HaimY#tmi3jw@s-DAgc?INn%%T6 za(TNcXLr?b5Prvn-c${$;-#mkU*B%h^?S)J#bgmGj)mNY7811RLOi@&nK)rSw`lEZ z{W9fS%dT&a*A%#h9M|CJSgTI289jczuOH8gU)x*E@ly$!2SS@n7F`wX-2$t;jZ0iR zyn2AtDoZ?s8pdz+%gHh#RFagI5= z3O(t=7q;mR*?%4N^2}SLkt@$ytzn~4)>7Q>~IVC`W zb^*&)4NnjL66M@mYtQ;K)|tRKV`R|)&!jI)1R@R#e;+CpP-ll7sWfW+X!AVwqDX+e ze%z$NMzRH*xSi6D(^ej)hGeq8E&NUO zvxN|%Y@St4`rq@y_ZfKKO3bfUl_+gfczzc^xRyLD$JC|4dY$5*_>J}TQ%~pNY4@yC z#qMM|>;Y#Q2wPr9@+cn2hrXVkyyg4V>a9{-A4T}xm`?+wy5%&JtRmdW{%=K?3kLZF znD66%IJf?tO&L=QC%mX_UZn6+OHHqQGohBI-hwcw^;uB{XRV^=9T9Uck2j5lZFV^f zLe*T(#z7%QeO@;fa7534+xtp(O#f)*z zD`UqwK*gXq5piRU74^ z{8i}I=XF2uIr&ubhmox{-ACgTAs;__xd(;CoMf$P4+Uu+g2tVx++|n2&RqvH?!jVQ zARlVU>?=xDq(YgeRhfEGotg~70|xRT7ZZyGau2vL@|)IaVy=Zn3UTT~N3GwKJc)9) z+=T+EL>k5oPa*IP4B^n?t}wTxX3uSoPfSJ8u+v?`uhgJ*&aP<540HLxg>98h=)4-_ zs-yMJ$hocwY6IzBp&m&$awAW-`a{M^mh0vWA(6^Dm_*ktg9fg5O>61DhgH`|yX{*; zVaw{7EeiVI6qJ5bAX!@hD+u`o9x3wx9t*PCmFNYx=yRe!&YY;2Ezr|V|Hk1s-WP%8 zn{ST&)UYhs0G3`8#nxdLa!F8x10eJNCVIQqKs3n`$--6p_ z$pk9;wNQ)~7Nj^+`*Bg;Lybd%7`R$?*F=jte+8C-18**TaXH|Neg6tElsd!sYI<5t z;Wc@)AB+PoPIo2WarLL>ycjFXZx{)Jm-UC|xX7N(5 zZ@ZO4OMGM*ZL1}(;Jv-0Ec+Xn4c*EOlFpeWC!M-ApXYQ=a)@p1A+maK{^Y6s^?3lO znXEibl1yfOd6*Nv@cY?VpV-HJuc4h@MRt4=u}^pS;BGmtN&UkX?lJE2vyp3!!@O!A znfW%8GnwZ%zXYE-{X;dmg*W^&9kv~>R;SHGEm!qdVCMOXy_0hJnb_ufzC8kp;s&~#ZP8gfzSPMOrE|Xg5Bidu%J0%pwmac1*H8;X|Qg`CJmBVrD%! z%ha#h+!#hw>;q`Tp#%}MgoK9x0n{B6aN_k`YW$6!<+_yk@)+q`I?y{ub!)o-k27yL zJ5UDKww^ooMVF{JKiF1%pL>K2IG~D2q{3B;l(Jw6>j$IIoj&i2>Rb{Z%1#TOe9Qtl z|6A-=j;6QjC7>x)zsAAI7&Hb-18_$v;8Yv+@BuQtkYA3(nm4_t$p>A29wuSi9)G5Z z^J_^3*G2J9Qxq@{Z>7{K~yDn|W69@><8@xYf^_Me@AV<#n5AsgABqy93P78Ot=(-pAfJg?wTh#=*QR4>ygB!N=Z zObj{XR7hvpNA!Zr7MvBYIf%mNs0V`={fL0d(KFYw2gf$$r z(b-uVHYCsw!!Q}@H~wqG=l=?M>d(~wDcf}&2_1_tCWGoJVI2`+T+E_4-OBwMj8C}j z{bEAe%4zUz{nRrj{KLwC`eSRylvyn*0&{nU^JI+#U%H=r!;v@t*;wHv9=&i*cfSha zCq@GV?`Q5PRL;_Vljm4e&$VTixX=m!NeKvHzFqQueXjmiVv)`j{u3EzlOM`E-T0gq zq0x;$0Rn_DC9muKQwXykb&qamy*fsEaJUiea^**V7{{kY>jczc(T6e?EgT?(>AX0p z#l+fpipba0%ml6uVC`2w(^wsg7oz)~!r?!*Mwk9LY=z|L8RW$wOxWeGA`%(Gb%sBj z*uKU&nbWZ~_HkdsilsjUZFGUR{@2fKUYy^G9;r*m*K3bC&plzGLS#5LWVP$M=7J2| zS36)=@~A4{p1K28!S`}ViOMFTpkG#EbdHW3sbZwg0J)!0GwC0MXUB$Ry3ELT9YAm2 zsbITs$1X-<`trNz+XaD(4dF96BXJ44{!0-GsFe9{%*utvGsg{nb>2}@8>N>W^ub3V zJD@U9*%YN!C3PB85bX6kt6XrA+v*FXVWJZi)CvoP_m+^e5!7PzVbvtO4BmpC-#daY zWH$m*w4~-OWX~?5m(W5lhu~xz(WfHc?%~MhdVp`wic<<&=T+}xSW8i(L%GxyDvCO+R|@m{DTuL< z@4A3jmofiz{sphe{s&DS{dh^q%f*Z`fvpJZ+7kJA!@T;neR5<|viHQ|0BvWH_bh{x_Y13Q7BU|IsI8ajVP!oRvt8|SQEm#{S%Rzp<4ux3oM3^` zi$TFos4jp97`e0~8t%FMxi!afqsztfc3_ew_eA>7iL{*MWTPzAe0z6-$otH>RxA~0 z0x9jtyitukW?=#62o1zq2B7#W9e}FPQaLARoK+7PIh+cphPA-Wn^? zFb?K`Qfd`LoVsD-1(f0}PeN_%GDxbmX=N5wVwTB~dnp(o`BdFFo>(gNi)Zc01V!;n zSN>2}!tigtM8)~Z#Z__j%iES`pM$b_pN~;zan_K28%X8`XV`c}^@CmixTO7kIrjw* z`|o$=@629(?UQFQz998UyxaL4#;>1sBqjEGSAv#R9VHQPrfc;YRUqJm5ci=LOB)s; z-#ueR3;6@=weBz7EOig73~MQkD3#3-e;%=~t|zD4BK-@m08Zo|n$V1!--66S< z5G62EHv>|#3cwFN6SK&KI`fJDQbcCB{@Jgq57z~mBdeMo1#{={E4By4v+YmqWj!vt+5( zUutB;cf{0}4&RiT`46Fs)X<<%V-H-5>r}rR>1FDPjpxhr>1OU$842pT{Jgh< zeP%!V>`gAmLpW)sK{zs6rI;iCR@dYfkw6cH8N=LuTF%hjUA8=eE@hR# z+Kf+~oBGQ3QEM5dJ;nvi08%ej0sfb~ZT5j<)F@@|MfwRn*$#A~90$OXrP}c-n#8g3!1U z^CTw~YS;E2rbOHfrI46NL3gI8Nc*Xb_wdV)WIXfzZHJ4SZ|Lt#=)lk4p9=Jh+grRE z?7>IhvE4Pu)Qf!)3kHpn^R) zo$;MoUXnldm8b2Xalj-W_W>C`f)+tz^#RQ_C&1?o=nd~e$a)3zLjZ)n4R4@LK|n-v z6wLCa4pdXC2`biZglqn8vq7)1 zKg4&1_ByHhS0!w_o(1}4Vw@;ia>7&M1~(B4%ox$w%#Y*e#W9I1gYdr{hRnWKKX@dV zC8_+~V5%$cq7$p;MRCw8_PChBUltjoNRV~BBSmxO=pgidyCA8XPD_XHn+SS@zCKU}Bn79_*lY=r5Lc0{xM+3dfG_E-YSvl(0<%jC z48!}VYKj|kljaW{J-asbG{pm}=AY{U2}3dEh`^nc{D%SK3IDmd{WUZh;t+iTY8+M?X)b8GVF}idHcy6SWQorW}Yw*pMWn z58Va3yL}YuQU2l$2G}oWf(h^FZq$+okRkRpo(q~c=@Xj9pgmX55v1SKO>SVQ*Goj4 zLXWbXM`ys5Hx5ZMem|b$K|)ZpIbMhCmh-eFqw_#cK}QRLbpW5cyZz;~5=ZTXi`aVJ z_k=Sn;F0-Vx41Yc*b0mTxev`n>S;goIsJ;;+JnL=k}*51mycYbm13B;b_kt+Hq z!K=3=@Vu+amzmKgfgd7f)irZ>uq`=GDPhp3;s5R?0o8^8)*e(OJPp0!j6BpuNP>1% z|1ew{0eTg$Lj!-F(gT(*ziUIc1OAhhdC6D3Th-Bio*lQ|h37Hnz8`1B%h>U;*(w*# z!*jOSS8&+cSW;C%ky|O_+Cs^Jo=Nnb>w)IRE|6(YYv#a~I_up0h|da32T+?Xtl$wl z;JQS=k>LN=b?N3v0BD5s?dP(#aq^cvy&uicU{B5uxdkqhkur0#3bJQ{F2Zy_UHW~! z1#n&ZUz)f9u1o*X#I5XKOx!L|o2i3SfUvV@d@0uDNAw+my7zt&&*Yda!t0(Fn0Y-C z^kY+=G50rI>Ym%>YV{U1|nkvfcWqX%L>E6y( zwnSK^WUJyIhO)X|#KLBzTgC#|YcuqaluO!K@fwi4DpwutRv_eODgVs)49~eFZCRd@ z7vc2=86u-w%`;mC)gh6hh>-B2Nni?`>eu7ngc+$zAtQL)Zx(J&=7`XWfCYCw2Bg){<7R!6;HZb8vcV2zxDRcXy;U zh|HK-I!S+a%-9BAAxur6ZUQH;^z8!C)uB;H{?(I(lZwo|(eR^kttn*9U5wDC=QLe+ zaevRp)S?8^0{1nK_tmj0N-cuKqld{=Fru@?7{9CLKihkYh*a$ZF($=f#UC94xrC zpZ{QRRc&KEp_(apPhVrEy3B2h#Rb3q+?Mqli<}fJBK&j=|W1o)Rps(LG>k@vL@j;UT%#3q1DRe#dWHm&5Mxjw=_u?(qZl0(^ z(BwJf=dClg+zM^dfWg#?T2tAyQZ_bB>fTMwr=?aL@7hZ)xY{Z387nPI%6mN$mxN6& z_wjQ3u(sBvxoZ&sko3x2$bFhh(6@lT7_Sv=1>QK{Ln*5XTS;$=q96< zWTm=1;wAp{bDylcBWo2QkViO!F6CZvvfmx z%s%b())IMV5^6f)J+a>+rZtN6@(LXon1$Vb?@|vnEukO+U@4@3^H+>;o*6hyMLnC` z*Ice?t@Ym1;mEs7f8(zFGbUW$PdifLYq##HsAVgeC*OXqP}uq~gp7=V4~^eftT`9x z4*H5_PHxZJgB=>nV~szs2{=(1`HqLA(eYBrK{7_B{@qtyZ|Xja zWX*&39aJjxM>tDdGrI7U99zH1IIW}87tI?Db(*NwHK^>%$M=@pOdBVD8`89i>itga z^NeYVxp~Tl{|-s??R5zms16LkZnfX^OK4itn@Sojmaoq&+sD;BfAr(UGe^EKFlc9A zWnUI7)qJ^@C7O2f@Xm`qbFctfdn2O*=2!-LtgQq|Zi~fDc5hgf^0^#h9R5L=j-v68p_2F z&z?xa_N>rMM(*M2bJX@@?<|zRpR4JR=g#2cDA;9T0#PnDTN!%v(EJ*bR7A=rkRoRq zYzt{%2kXOcRc1GPW7KlxT=(_t1{pZ=tPcx*P`I@gx~J?ScmBGPAB(`K<-3`^LpkH1 z=O^MiB0h1xxr@E+Ck7yvpdG>!-GP{_`rOU4pX?4F6L7r#WH|g;-Tt2CU2~dwPJQ;Y zyryT0awkt)xFQ;@;erk!KOTaUiom>HE)~ynmA#bsA<-qX=)RJ}DcS317mVJ9S|S~e zc@3<^XAMz{jz*qThU-)AlOLv}=JBsQqnH>c0u2^X#feEbvazLYx9JS!nX!TFJ*(xW zHuJ{m<7tq68|x$U!z}vqJ9-?b2cwIqvolPi#>lT%{2scUaG{|)SH25pp>K@DVn8DeOPh{UrUevb*?`3`Z0ybZ&xBr>GJqXLJ+;!E&CQR5j z9Mub)vkIxmPJulV96o>sY%6=Ifk_(=E+yi~vP6{!|4|zo>0PX4d@FKo4Qc`nb@E@G z?ov3K;iSZ*wOGdwFvo7bUYjf9f|}aJ5eqAtN06(AFiR!ZgrT_?6E{zuCIkvj6o5TT z>W8|X<{Y4~MQG7IhAny(KV><^n!NUxK?=u2$a6kROw71vaH^ik*CTt!&i*y0OXr&A zbu@9|Usmd3KeH%39RrjUU$hkC&N7%WBTK#^lPm*)0F!_>L(2sj&p=I0j5}6?ES2N5 zz{BIuQO9Y~-;yl5`(Zw3TMWHQuzZa2%)D8$5&Y*~PY^3f$X3Yn!{r?o0`C(a>Dt{r zaG8*G;?n+Vh&|8RYaMs0Ai{RTuCNR|6#XAYOiQ z3B01@;F@%2Pjd9J2o{Tab4tG~IjA5pLJh=AbPmi8S_rH(kA9CGBaW)mJp|TGiKnr+ znvy&H#{Gqgv5syY=WgZ)!51#y8=kw*4U*RjlzZ1SOl*2{K|nao13m5TfeMj5Zb}li z-R0_!O(kYMnlfEW$0cugwe9>i?>0XicfG-fae4rdrtD!YIMOC?kof7uh2#9uche;q ztdr-o8R?#8#>J(F$cW3OHK~^nMq}UdaL&32ZUg}(?MQkN(CubbUCB!jLo$?i9{5oNgnrCrXm)Jjr%nnksN$B0|&%=bV+~$ruWWcFcXo=yvJpIf`rQChVtAHtjFJyXow#LGD#Q$K;gkOv4i8$uV8trr;2s+ zf}D_$T=ma2$k)ZV{`unp1eLsbZ0q#Iqu^WsBmUa>-0Y%fkyGF`tE0`OHH(h`A9EHi z4#ydhgCR0B-Py4eiTbI{n&&|(SBc{^<(m%%Ez-%{HK*O3uUL3)u&0W`cbXfzQirJZ zz^Tf_b1Dw6Lb5lb>NzrIHj7v4g<76@k*$ZS)5&u+r|-_~wjgfo?zLOS)!!f~_Fq`c z_rj7}l+?|L;WbxXB)fYA3(e%bzDB0SI}v(|cE`4SU#zB~rE z0wYk;gC3rB8;VMTD(`+ag!}XYWQgEULi{ZB!k?Z4c-B(5@acO{u}^O9)x6{LSvtvq zLfq;oGPGZ2P^mDQ_XQ}hjsBFjaHG0I2 zkUC24uoDeTy>0L@zuw|m%`>2{v^WKj&XLXVPGwZziHfjUr0GQC>_P1yF^&ERI1=uR z{W_01aP8iR?5#+lMIx$;VBNPgu{4VgSlm$dYGZh~DMUn**6D_&&r87k^w7=4>3#X9 zHyit^MR|+Q9=+hNYkC(obTm(9HksZwk7@cAFUmE3YPA16<2j|#1@C0DuOC0>Q>oRM z9}d<#A_o#JMNJ+c-o4^BZVgdXdiyX71zI!^Iv0qNAX#P%w)sI zhtCzFD`E{A-jtWmjg7RVbBm8DHLmyswOb~eDRMD2dSYE61X)*8w)iyj2+=cV76UDW zEa*G-r`9_xyDTOT2HbIS29OA5D|(cXi6O#k7);@sQnJ(OnbD`oWR z;3Tqdvp=IYMT_Ucrmm@bo}+xXjMDRAbaaFJ((+A#g^C>`0Vxrpl^;VREXef6b~#Mh z{^-l3irW40(O(Sp&S@%u_8bzs1&B*8wpZ3sv#F>~$eH;8(Jc6J>G7PS`}1a69U)0p zM|`v04$fCv!J|5BugSF_v0`gF1f#%%s$c`m3Jvwh^Xa{Iz{viJNdyIYo0tkT@%!!t zmr-51K=}&PHR$dZ=t=E@f16kb*asi|<=>Ku{9Ezy@AmyyAN|k#3CyrNelK%k?{gF` zB4cZxr5|x2lgxlGzjS)iLo2hHFxO%k$XHRfdcZ@MBTRpODLj*2&;Z&>F1F4zp7g)&aEY$QG;Jkk9z7Fi> z4shONF{3pk)1NE{Vf52C87E%CLTn3Kz0Z}zT{!dg=*h>tkFA)5CIL1Cid+XiLmvM+ zGsN)WQ6RpMW-9H=Tdn)*>J!L}1mdV*;0#4}Xl_%#7Gg4O*8^!Eqsw$E?lk}4-;ZO& zF-Mc-UMq*BS0x-a*PJyUX}L%&JHo~E{6^68`I^ZXPlF*EDz>=L9dkBVx2JXhqWbu+XJ{sh?>oq#z1_JDrEH&?!- z$8Lk|kKR*sG(^ z^eOCWIMDvvw3Y$S>Q2;oKt92_bpYfVa3M(dF`)knL9oJs|I@SuSmT#)o63tT5DIom zYZbmR3lI3XM1islWm!~tHHbm`jR2%wh%piHL|!JIhfyBpApw?V6@v=7k*c?rKp7Uvo33H zR(qNo`q7R45^bGNG%cs(*~C}=tWCT|Hd1`7dj72D9gcXxnCsl(pUd2o?< z1;(E|mN{f}e~n?MVj~#XqH{il;A^pZDhK9}!wR6c{|Y zZlxR8Fwb+Zq+CbSYf>RZWn-p4yWLak>3iW%4u2PGC;){ns25ODPSd5h&cK(YF|R0| zvmsPbuxFnG>^=o86{-45+tojRCbv3&KjG;Yu%ds-r8L+`>dWpEr5&|KM*lt5D* zw(Ic6E=XZl#KIQ*BUm~hJPa!e(vg7J-cOF_&kGoTbE%~X5*k=>ip7g<4hhn_GuqUt ztdP25IMIyOW5MW1Q(YcukZejd_?x%=&j0+4TU6K2w=-T{DzQ zCLDOfKlH^kM@&yI@7ahmuyP>f-=S#Ejlo7br-M^Ie;Z$R*HE7UKy;_Oy@U7NiN{9j ziUTV@ST>8DpzF-Zn|4Qm(Q|FF!ZN)1(`G7s(sptAJwP*7104R{X@L7nbXHJBb5P%b zbKv~4@Q4r~pFmMUw7+wIV{Z@fY@l(sXj){>N~$wtrZW#dBJVbhpe8eSECTHVA;uZ# zmp1GKFj+8)aH43PTdX|->@Gn$*;&ofh@#P_gFYWOH!2E1zDhhE^3U1_9i zhuHf7fSc!!R>ih|*7nodK7>Em__l5R&Rm8;GA7zALs$9vyHoc2Y+aOZfq0tuoxeNg zi>p66S(VOK*Bg0|^Yd=q{RQ1#4jFlJ>bHgVNA`lo;a{Oc42g|D_~Og=V&caU^@o4r zBmvgLpPhdqY}+Ak$C>T$xt;86=WxFRPl#3nIyWQUrFwqg)^(1)es;7e$z`=p)AR6U zyqrkhvozry^dUlqcMU^U@WJbRFK#y;R%<+>!sr9f2n|0&mw`RTKX3lKw!|-1OvB9R zUO>5Wg6`;7Ns?^^#FG>HVdmOm<}#=Gd)`zY7VCB4f81;JB+l?TV#p<@qsO)u`liD> zAIUCa{ES&tere<4YO-v7P;F)IgPcy^h87HZ>KefO0@_?fO>iOvfIh$Fd;@f)l)|vt zWB@4@>JE=lhfho{ZXSkU&}3&Kl#1wq%mhQG)C&Su!HV!@A!>}m76>c|??|KrG_n@E z7=UXCO9!-XfMVt^*MUw(V>ieO^v4*|BHc_e0RX41vTUX!Hd*H^Y3dj-^(wHWA#w}U z*o0jX048_D!AUe3oDJ_i2=72xtGSEv)m!txPX*}jMuuF-iO3${Y zKMvqP>yve;K$C*ZB&$zm;5QS1(KRUyna1ng z>0CAVdel!vc=6le%SGCOg}WiG>;fQaXgkz+4q`p+!R-w z@i(EV;inN!_m3Me{2G%XCm}Lb&-3i*di^E30_xdL*N@GAOrpN^Hj3Khe^wc|-`;WT z)6;=z$XCBX(|4XNEUh=>77=qRi>jWJ4Hn7Ak_4BD{*b>3%F@_BrxC*F?L1>U&)ANo z+xh8s?!H~uY}b5$sfX9ysN=?y_-ZoOBxFf9^-Ur2hKt(5a@wa!U*C2W5GR{Vb~>td zC1q@_2F07jcLDWSO`O{h7Hz@v=Gfi+L2^kS`hTsF`2RZFMs0Qf>;dhs*G=(0R}1V8 z`>rsy^O&0=)<0fvL@rXm%X{+U4a5Vp4>u7<3WH9LXj@kD#xX?o5(%5f7UKbaEHxHS zQv-|nc^W^P)k7k)_BWo3|C%}MeNjeF*F0sV`+nhZDHU4PwWr3 z3c3g0ew*&-&w7P?GedLv3){r?bN*sO&-h6YE*4OlpiFA&qYccb@u1v!d2j-v2Ko|) zjQs*397Rh*KJi*@fetu!xp%I{o6IzRdq#NeHpew5+on0_$#3x}QbrC@-Wwo21dVU` z)-sJ86b+g9LRCP%y_pdt@{8gi{?~{8zdWgNnJo;LYiJ zkPRcg_rR$R73s>QeiDSlOd(0O_5-X7;b4ceZanbvCo&O?UtBe2>PiFG=&f@bQ+LDl zr(4%!Tj}!7vv$h-Zhd0pMsS-uITv@q)$KJ?-t>rzTfL7h!`B4d$!A-jd~W7MoMorC z@uXywa-ti!OBw7XH(*!COH11G-?Q~!|FHuA-=5#JJJ|@MdwS9@B!Q_706kTJWH*?C zDW9k=pfB)})|G7l>IDG3Xi9uVML}lR%-j0m-Y{@LJ4Kc*%R)krB+S-$F6MlP>3)WY z2QJ%@y>Jw)jN?5aXJkcWu|)H*+9R6n?ALSt2TPgxW6V#~_RsRauJh2!5|iwJ99fAQ`J?z(CSorp9eH2(;mahdIZdeNxJ#kPNYfZdX$DV7i)|YtO{r) z%h4SWt!SZ!itv<@YRQNaoNgTjwg6qb5584Yz&p}8CG+8tdpyr=vr5B|M4sU@b{2=cvBE?=S zg-Ol-QP+oNNv2t)WVdq0u^lmd%Cpx zxLQ>QE3~NJ+o08~qkP%}!Al@GlKSxJe~9R3m`hVVLJn{24qt8UCUV`8>^}isZ7$o+Q08 ze_N0;9I{Idd2XR+DjnfG=ncruLtj|&5(6@N=qMRZ!OtQaZn-o4{;R7ECAn9-$3~k; z+WcO2o<{MZU`gG}T!UdC@Q~O63S&WTOC6ZX)N|R#ts|{T|MmOvFGU&~UDZ41g%^o>3lgOF6 zKo4q$0d)1*qkf6v7m7Fim|YV}1GI=Hn&2BB5YrHr8e}xPw~u^Dj}f~DX>{aEK|@%j zVx&E2`Bci(zI3hLP$km=K1B^-%x9QkuXO!Zwm`S6;H2=O-3dv7SiuCZ7c?`WHW?zP zaW&_juWS6-N>3RD^AaBm`-E@|j<8~o56#2x9B6@`4}2a#4nU2Obq$Zk^j%`Rs;9~2 z8pC313bxkovDqj*7|q69YLO8id!kVkX+H(^hqs@AIl@x9Pf<(zPUS5m1#3w(`g{<) zM{a0zBOcpPh({HlzndoBkF1^t=s;rZyt~R96IKIiz&_<`X-<~a+ojw81JF-hu6zUY#hv27T#3CzxgK{Fvf zAhWN)Ey`;~5VFm{sRfRxvgKf<#~6NhO03vieJ!;MxUFqWf{+ET!mBGrr@V z@wf37mZGM-&zdBI!3RrutPmsnJ>6~{p;aMDg7V0U%G|nd1HQY`2NaGyKrxs6eHS&4 z6Ceon3`rO8eBB+yy3SIbO$xe+$23Ei87DFEXh|viTzKa2h`Rp~x6?Tl@rVU0Yv?Lx z=%AWMg-+j6fT}>6ox>q(oG5E48SBe4-_>|`H^~QwO%p?l2G&{=nE3jfG*x_ORfO#v z_?25x>9ImhM+?0QtvceRI*}XsUsFE~yQ?D8dk$U>_40!|CS2I}`udZHg z0*tC%8u+I$Q**Nykp@36Vl?DrBV_H^n*VJ;uX#k1;c2#>wxge(yXkOVZz%IIsyW22 za*wawIQ}S9gS1G~fRNjD3vh_E^v##GgUI?Nny^wKK%k-fQ2Ha`?I+=rpC8e0<)g>> zB@|RC=&+nMGwPjyuvrwj3EISkXr*ukc{VR+_&xl1WN+)?{`-ry(Jv3?RrEZl+`k~n za3yCcg7?ZyQ2Lx_-qSS5TZsL_#=VWI5W0I7@o<~65lMpF-_G8sQ(FA&#xsF?4yXN& zWL*|`wnN~}bE%gnU*B=^(ogZVuFPEvD3H9>GLGZsV^GbhuDA!gZ=1RB|0hq|&i5ZU z-+!^Lr3RB&sN*d7-D#Dg(XR$G@kvDFB`StZ@QqFzpDpt{#-SZLs}n6sZo2c{@g{X| z91W}NN6Gir-4?SzU!SA3A?MJd0GC)Ou*43>Bp=ySqCcCb-!8y7tK}(o;kPK>bakX}dVhI++D>Ln=VBA& zq&eM`ET%>D&NzM(BRPVkrCoi@Z){DIX_ZjB1B)NUB zC>cmQkN)cn_dba&VkT5{>hJRR$2q(a+ zeF@ZYLHe~b5d8jG`bkOtVo2pi1=0rHpk9VHmb|>_^hfNo|3V#{9}X^x;HmuBOLqiJ zZp2a(l+A!GD0{a+H!+9jw?NBP$Uf0VjxOH%B=5$bd?UPJ-Rrt5|06NRd zfRK@yur)ind!jG>rk^i(y)J7p?bq41TRNEamc>OJRON+x-P-$=l}m z4+7;Mw}bkR4&T3Jj%%~v#UMaXDVBc9bLt>OW1aB^6hQ2eA|Pbps!E_^-UV+WV7S&| zsh)yWL7xV0Z>o-v)P{Z+aqi#ylF+T6Pifw^#%*i-cY@=}3}g`y9a;to$8mM#2aPKT z&$nVjaB{;UH9pM(h_6NfJsp)MIS<~z>%ym)8(F$|u}Nw_4Y2>nGyI-oCy=cEwh=79 zOs94`S^bp{?!OfsNtOjpp)Xb?KeQ$O#vv34x~DsQg#GClM2p-&B~lsy*@~#8F0P;6B&AShTz_z+ zflNRXy=hIcfYbxI!C5kg8Q*{ z2HlpU7sPs7JC&3Ey(-}UQ0Yh>!KCvTtTWQx0haA)3;?jj?}YSu)=}V8H^J4gg8G$^ z0^8JrpTuXl;$gTib{5=^REgBdp|}GN0chODU|W!+o#8=Ss;LWddTYmQn^cp1P(aS&K|xJ07xr)+Im+~ zik2v~ZGQnoj(IM={Sgeb#6cy9(ImD&Ys4*3LEzAu-EtsAtCnI%*9A-#^<6ek1;AE5 z0#iSZ&@)>jJLrq!Gc=%*;RF=T(MCW+^)Kk%U$Z{`9ozfA6&QbJ5CzixwtYUA%}vv+;lPxm2B$pXUN)cclz1hp9hJ#QI| z4qO(+{*aei&AA7inB&ZL{*B*&pW`A>zrg zlw09?3!8wcuUTiHf9rF_ZEO5P zTVpUlZ}P)!fx=xj3-$0vsYF5tP%XxiS%6xR)B;^=1rYO32~XD+H~RiW@iT4H`Xd(! z@Zb7qaoZq&9|pkK!{IVPR)D%HLA>E`KNd~hC9b=oB zeP{4q4|c;V5A}!a=ngf24&~$rSSr_ctAj&6u?eLfP!2R-#7xfW+_V^8?I!w=&JB~y zn%7`XAI1}emAJkb(|YgT_k>1g1I)?OA%R58fw}INt?p^&;{oG-unasm)pLTKDuQwM zLJc9BM*Ulww?J`2vM)+ZRE!JwNBo(=^5Cc~P<<0J^JaHY<`VR-U<*GkciC z(hleYd6K-VWfSvOoo4q|U+??S*U!Rzw}Itz)s6ew%H6EXyp=9#iLd5(l#z!TtT|oE z`Pg(V;dY)O!mpEI#q?|B41H2o%sr?i`HAlghxey9ioT?C^$Z=(a`(Y5H6kA{XXaCd zrG`Q$LioHXv)`K98%0mpOb@=Z{UIFRV9zXhJqfQt(ocH$($g1J;7W2U2XbL}x|$0) z0G9;s&F`mchc7daY=Mq9(X7`ig`pb$9~=|^sHp7kRoZWO+FElP=rO&d_V+=ASDcP1 zzP&6vlu{_zcQs@s=Jf8e;9VY8pC3QE$mQ4(KFYi!E=?36HxG8eTnRrIz z-&!?#s8KaCeN`(VY6fmR7x)e6@Q{FBI0Js(uB|W4fMhZ3Xe1vUy(9XNqE2=@=hX+L zwU?Mbx}Mc0N&9OwDC!TT!QTgX%3Pb^RjoS>TXMu^BxVJyTcPfw33Bl1ge_2M0xb;x zCr~7K81e%s(oYb83e&Fv3-$1O2&b(4UHOZk>f4GkARKC@v}F?%wAk>W&eWlB(j4vO|s`@s9vds#jxvD8Ly_>{>l zFC}Zj2}id;GQb{CbHB`cL8g|+*$c0ac>rrB9J|g2-4_f4<6PC}!YhZ;ny3rBXAn1J zd9AZ){H=Z&dvw^yaCz^99%K?E8HUEKKS!S})`a^Ueas=BXwXaV(L+YP4p+SD!zc%9 znM>-m>1p+hW~E8c7{*5x)1o<&=^AtsU2*|FS63w4rn`e?wP{ETyT|{W#n$7JSf%kx zxx)FHZXV?Q$=PQ98ue9AVe#7V?zPS4b|(2T5#riXtEq)`wx-*9iw{j}!s z?6HRGi!CdIRcE1Xy=!Q@2-m~RRTGP}DrAJ@75B`M;=_y&7sf8VV>0ZzEX7}UNWH@| z0}mG9``9^vcpuUWPk|)uBWIA^ar0`pPrY-CX+yMt%`oOJgU>3Ayn#+*J~E{Yr3qpAh*?bj7*TarL3(9SKe+ zZNeYm)| zZ*?r=^MrR=*{nxO$XA6B-Nt}9H*zhe8J(*thL0}-FWR!WW$ocP{JIdaiujoI5n{`k zKhM2B1?I?IGbr*^>CwvXT=#-x;3;TnH%9+h&6b# z-R_}1#!gk0#LHMVVpn#njeF_vgZEcLOs_b{;odG(9yFw!1|n`f8Q3~}uC_VHGpD}R zqW7Ws*o{E_Jct(y1>{&u9<1DvrZg|>1Pf3C##_aK6x=f9zUR`!HGJx#+ErS?fE&%rq3NxfX?#ZAwbxvf)zxpiHk#VP-!ETN1 z43=7QYJprnN2RLXU%@Q|Qik$dmk1M$aUT*^E9nq;_3|z6{nopdPO%9UoGg}F%V`Vy zGJLf)I9o%C-)-j^*zyyXDdclVLO(RI#-@l^l6CsYa8E@XyyE30xl+uUG4)l(S51eOl$VKd0NvHGIE~zhlTv{eE$E+=%Jw5X>@P51NbqN`$MPs=2 z({OK)p874I#M$;kzjoJ^fS}^DaDu19NKTi-+&>TB*sl=u;tk}nGkgMEy<6bN&6di}002~;L#LTisr<9sz%J~hOve_fBuLj8hpe(y~ zKib#V6Rej=M4NJEn+}?nG04yh$&zAGr;g%KYSwD4*=4mX|wN!`z4^h}3&d z7$GOE=B_nLt^jC+d5r21DX_!+MUF>^h7H5YqsR;Xd7 z*??1Ou>UQ9b&6?LWwA~bP<+HU&JyLgQrLax0*epaF)0w~N6Hw?Ov;KS+-n zDa-f0&yji%Qhx;C$`5o9-8}1PDIK##8!_o$lvC%hwlHH3?wTC81s=v}NWse3ZKcCN zDYRWE{+h#?%%nbq9iHnz>H*`Y+BSZNKS{ZCM%VA9hm@L^GCSOkO3^;#9C+vonpKfP z*3Ko%w#U#-YY&f%w%m;#h>|Ufw0(U|!L74WXb(@(P%%#~!XWGTLwn=g%~PJ>+~(AK zFIBSUAUFtaGz;ezFI<&jUH>{XNGs=lR_ATg|Elhu7HX{uzK2RL5-bW^-Z@?9U=dnoXn5U@M`qw^&a2St3_$ zySG3yJd(8m)<2eS3E%S<%{He$c>dD=+umb^rhAZxsFk$@FkS}1<5pa^vbZy1Y#|a(q9-0qZa_7o$tGiVTBAD3rUEh7 z#|cpzcl_xyVzA4GA;cV>2HRQB4fo+hKa5?aEGaP`dd){UsCKz?b2N#u=SSPwI6(JI zpeMp9e(-@BmjKC)8gS+}8gQ0=SV9m3Z|4KFNNp522ez1H$k;rGQ|{UtXa_&19*kXTdv`VAepdDF?iv zKm1+dB|d;H4Y3q~&B51Bnjgcn7McpU&@iOZmS&(JoO6fb@ zR_Skm@+TT^K7*sy+J}LoE=Ash>XH@2o!NgV}5cFl36};yS zeBrbU&9eq5>vIRNGh3iJ33%NF^otPq7$vs}7(f9$VfyusduSn+=HN{dc^qwjy23vtjnmA9ESf1IbSxWf{M}ugK#F{p3p=$$<)~`CgH74Ig)-GQtQ{R=f za$KQ-(kPD~x9tsA3uF7cT#ge(zc~l}K7`GbgBa)%;~*THz$gAq;wb);7Xe+2v#QJR z9PElB_yw@@)lr>(#2X9f&*IYRfsqJ$(;#+LZ2LOf_va^t$M*Tzwu^1QvF%rXiFlz# zpnF=A_7gcpMA2tsG)}8&vR2hQ10oxH`8!5f`&oxA!XcAC^e>`CJ03sbMMvU~l6`<6 zDoX&jh=^2G<`kbi@mCCM?u!xgpD&C^>3nxPdt5vwI-#xM40cP?$K3_1; z#4SZ-YZSfE&YEIlF3agLu-FnbMV5O}==%_>jxR6y^^hbRB!Vs#iA>xADKXHeTT&LO zhXJruF`Njc_3&^w(4dG@Bt@IPAJ-`TdSBx|du7y1G+_)$7IK9w@%6$d#|b@3rK_s+ zqX=3{j{_`Wl=F?pe~&8mOKd)XDUtzDn;-!X$6VY3Rd^5-wm`dp-Mk`TDv(usF(6UmGTL%cGWE#ApYA1lnVz zLhL0>UYXwJ8UHU|`Jd+3QT<3+bX`pA7AWljFiys``_T6RE0IkhWHI^-b67DQ)fnTK zCNcZpJ7K>Hdb$HjTGXXJF9mNLazqo|J!g1_H`9T^cOxA)BZbyl2=A6-{;!?2Ut%x% zwoPr@)UW3?{^6B><2Lp4cbjk9)F0iZs%428%}J0{=~x`V^=WZu$vsd~X;yL8PP;kH zv3JAKd#P=)XcQR&P5#`h@!r>0gDW!mQ5Rju2yxJ(CD<6JfoWT8DT9kiUl6(1pJaC6 zgOh&?+aZnt5QvBLhs_b>IFO1-d+S!+)3t%p3Kzi5PC#2MEGeO;;C zkQ)-=Yu6?o6eAtD(nT#tSxi}4#5lOPm|Vsv2#H6rgc}-O*|Fj8#VDOxlv$sN5jF`u zsc`d^8;VbkCrSEzxPUcpXekaF&4JnM=*l0`n6nDSr;fk8wWoQGla7GE&2InW}~7@=Nq5N65LWGLxH>wYDVTF9&VxAb~sDV zQj%B7D#Ciao@qQ}xGu9t0)99xY|!${^s4WP`0J@(ZoU$tHTfKeVS+XGvH7gS-WYFz zE@5y8vQrOw(iyUWS zBpsW)Rakqq@S%fAd0Hc>~M{J~)%s`1U z;LXeg_)8ZtQWgn8)e@U5^FbD^o*97yzr!ozWEVwG(>p`q^6dKF9=aSSw$lMzK@IiKASB07FiaX4pq>bPm2-%twTvVNsxz!~h)Y+@4A zk=1gwGoFxJGrHwP?EEq2Cz9xnWL;IFHq{c^Ay`&k6?wkjO)}lk7WDS*+nr3x{MWtt zWndlN-b{N`!dT;8Grs+j9(W(b0+(!+ompyR{T311i}#L?#kTQ0k8=^Jd&hR6gWcA; z10d$!G`Pod z?&r5U@Q&}%6;-|vD-^7A3v|NGEwGI4((4AxS<;|tf%GaoUY)9scSs2 zr!z00VjYI=)6Tq+64N`~K6P zX_sb3ebwWYx`))>Unue+b$4cc9sj(h_>*IEjDwb1mvra{urfnpb`o}W z)AAS`RnQL?zU6r5|}`?dE>X<;*&6RYW)D-?4+MrWqRoB^(ys4 zwJ&yGG3k7eKiKOHy=^tmBb6DBWQTm#_@>lbve<$YA0d40YLwa+vCND(6eAOwboNGW z&WX5Zht&1dJn9bFmvP5`{kaM|P!%|)8bUN0fqzwb3oLG~$7Bb%&4f^ez?6jSE}B?{ z-0(e9A$5mTnn8W8Za~=VRF&*K-sh<}<|`AEZ%3oE2+fgTCId z6A7%*W102pNdEUc-Wwr8H`9+<*K?6d+d1nh8m&-o(C2`~WGlLgQ(7p;evar7sV?;f z#)#`-SDiZxP~EBhMfBEN^9OlFRr#DFp5|3Ai*{?KN7}n{Q3H7aa@1diXIc1P!ZQwj zy0(gj%xR>%BU^a#SH;L&EVS#5GzJHBDkKFyZcG;CAYOL+XU??tcv>MwW8P!lE9;HuKMnLRpPwfg-pr8$e{w78zv#c;>((lpTw?Lt;bgd9S3gmhdoWNQ2LI1IA z(z7Pjy5gw!j3pPJ8ZRC@Jtvd&A?}Bls?7Zm&lM3EBnh#Jh!?rjCv_Is{$hGL6Q{#1 zaD_($6!np*=?G-9!&t7pZw(?4BPhV%z$k8bVjVkS$D%*jc&uzexgV3*C_f1R_336+ zB-bprmkv%h36360tZH*@a~bg3d|P`dgFf7`^j6xV9A$i~Nu=i8U?*}ePKl*ScG(Yp zF>M@AyijXV)&9ir#m={Hv-e7EL}(6#4^mVH2c$Un2&-L>;>|tzga`sDQ8DMSxwYKt z!7{o=46p2c#;mIl8lATt7I0EGpmj0cARocoNfDwk{yE{k^|9T{U;N4jmQ#XXZAt>D zvXtBCv=agaZ);t|K}*5xFIWzl6bC6ipjYQ32d>3%#PWqMFoeyQRbKGcS8NMH=S2Et z(cQ7oj&A{@ye6v`tarslT-8g=<8o>nEDD~0 zSAP}G)HFK6Z^i6BX^?-##Ke3ifpvQGo~}}BTf>D8!xxkt@waP*yAItym3C1;TtW(b zWeQFT->jZZ9d;g-b)0iBkU{TNKS~YKUED=sO6IF7VkI&>rTQ>TY85pOdO-A1 zC5Ln2?cy^=%bZdcI$Sv*!N;9a(){mFyyl{GZ{U&;wnN>(5;typk_&Ue*0VdR(-CZvUy7;BdD+9-gu?8uCa@DAC@~9!eqRU$E}K&08!11 z3>dG@jcu+P%v4QxG7S#1Z|^X*(B3H-W%5=|PZP9%z8cgHFP56nP4b;+mf(XbMO;Ws z|8$b^QX`2eZy>i1B1jFrO@8op#KE*Rw*H_@o_w;mp{q)-y`Rv2eT4H=Q1V<#P-a~1 z3BJA9HMs%;PIw*$iPy+pjWzgYitSy zpI25KODhqob3Z6||At}2vE%cp#x}sM>g>L1(zI+%Jr#L))Xb7vPU2~YF$sHKe1SbQ zwY-ntKJnG_s}(Vv8tJ>dcG(H5>_YE`5y(1X4_KpMh@G@WX^ z@gaf!;nv`C*{9(A%@tyf@u2rKU`VvQ3eNNL*?mKz-h`k}Te^H~&~e z#;e@U&xj}~jKX~0`EEzMNX5q=)_G>Xxgrgi_eCjS@4##T#(6Q4erpar?rxX4Mxfdv zXKEM2Dth6bOW^b+c0UHpNf$9!;nN&OY)!jb)+}Yt)lObv*5$ovt*C#Bcgg;>M&n)D z4r(Te8~MW0fWMVb_gwJ@*;CK_GoDH-V%IBEzllvdLsUkmiv0ou zVJP>&1GxkA@S2KlCulC_l=Sk~dU&uOa~8)FIn}agq7#OHnTh?F7k9(C#kLOMnA4Z_aB=3P_kBWN#o2)T>KjJ>iWg!2oWVXfv`&#F*_ z)k2W5p6BVdx(MO$fTH8bs3o4Fb`l}pFR^t{08`)HuBL`D?nRO!Vfv*Xipxn0Z;qT7 zW2%(Bd>LE?e^cc&uxA;gvL;lNu~*9wA`a$L&e&9DtRC^UJ+$Ks44jEq4x-NX2iC(S zretGHrZwtsX&h^qdrAA?m0_4;YINUaTqmT2mW|2z5_tAlZKiY3WW@TybW6>$^zrFy zo7%f3h`FQ$qi$&vDU{S$N&9n;ahaHztHq}yF*7n$6^ePp&czZ*!NDz%L*aPyi8OP) z=-lW{Hx%nM);1?C*5XX_YiC|Mk^|nZ62Z0wx?W6TNe~keeO(rjQNiA=eu9bTg5++& zY$+7^LQuhy#GOcUiSW>)qHN3)(b8iw8)EiL&6o7~u<~MQqzEre5H*@w0+kp=O3hB~ ziLe^E9~6I+!~gjFC;w8{Flx^%Eq+cs7l}xiLcq_mZZbj>0^WBx1gh4Hs?G;l`=N%& z$Y%fG(#)8?!Xd1%v-jl5RsKn(P*a5Sig3jj$CcP7W;IEaGVd8|Luy^&!56I|?lduA z)fge+yIWnw0vkiuP5U?d&~LA;xZNrT&ZaDlR6d9NE^_t45uISVm{v8I&$NH+y+FoY zlw#K7tJgwYEig~@bU)a8@q{6ZrTqd=yia+T`bt&_ZkWL4?_k>`%1f%KL4DsAiXRm{ z?74Gjtb^_PkU^`#(3PvyCpy@37=t-i)ZT(xu`>YTb8zqf$KIRAL;3gn<0F+egjU-S zB}-&W!i-Xulp#fkNwSL&8qADRgcw_PCfO6plB`pqv5$RcvdoNqnXwHs<9mJX`*$8^ zyYKV4f9LZ(_qosc_NT{~Yp&~kz2C3x`FuTJ%n+>I)T?PEfhTSMqlbRZu@2<$(8`Na z%{qpcM|e_7f8KYx@``*g;F^n>>6_}{LVAb6m|5voWBJ+B%y~zA>Qm-t^SU${nkpo}|_Y^1M01cI#Rf7opj_jP=n!-O-I;Vs`q~w^@R7W8REYh;p)zWI{LPx0TuV7MwN=o|ILAs;lpMSfz5il_ z<_a-#taOENx646ca-J4|f$wg(OLi@Xa`ZvI^j-MT<$bJQ ztUO1Q9Y_>zchGJG@9QB$V|g5Ja!z;NPu4#&>6quC zz}9IGFWUj_<(9+B4Exy*qT^c?bz)SV3(MIM{T1mK9`yYh!YM<|b zu)gT2f-gIuuYo{EZA=)}aGlu8y=em7kTc5Kf@}V(qz>P=81q?wWJ6(1%;kHb_? z3TVLZquVuxX82`ax)%}L*?L_0jZXy|i$DG@U0;CUdP#US;cH0A^b^2v9paD_do{W! zqpcy0^{?q!tWwhEnV3cWT*h2rxzl4>r%RBTz=-tL4L2ixvuAl zP3xG_%GBFUuV0IGTwU&99eIJ`ucW%s?&djiwW<7c{AA7d? zxmu13MB8W>81ONqhCB7YHw?8W-GlVu0|I25*J77kFCs*njSjC4K6e z@Q4ia{<(Mrh>kXErAz`kILk*;!7kfISfj|-x8wtqE_$D-j8-9%3}kaGC6hwZr{2(2 zXgRGY^XdpoZR(>dUq7y;S9pp_kK~t`=`Pf$Ya0!wbS`z`Eblz2U@Dz zd)l-u5@}IMM+>vw4$+H2kWX$>61jU94!s2sp)2ZAW2$|A&Y2PSc-mE;@7eeP|C~QD zuLe62yBl|8Ghe-?v+5`kXhOJH#q29%l@-m#Xb23*nxWfvK>mw<62Hkdk@<^AeN~jA z3(kR8%0KMS9g!wTj`PNd4##^=9N}9?64H4UvS?{krmmT(9szk6W50(Cb&A59|jkPF(_f z*4sa~FcTgk@vCM$D2zBz9MyB!XSe;iizoOa->E+T$zyS3y9IKqw|dfJ3mt!sRpKsa zX973keYMZLcTne+TED`oMrypJ*r8L6$6Gloyu@lsj-9ks78*s8&RN{(?QS;x%uqIs zJ{t!%;~`S(>XaFU zF(nt>f2EJFHBRzJ_pPai?C;uf&a6YiaERIG^_JotkX(WtMv}%Vhhw403ZbmP=l8Ut zwuu_{{Bx;~jG3Zx zoJiR~HGvd{m2}ccHlw|aW%XA7>|U9w{hm0R*68%3=%x%GF$hnOX7EsbYEonBpFNw| zIF3izblOrE^APFxfXO({iVbk`0dKdcBVv>^=YpBZ4lUZ#s*pc?Sz&-Psj5^15mM5jVx_Fuo%h+ADx9v1_{^ckF@OJ2d5Vb-U`orJz-;{Z>JRBNKk185~xXzV&Jbipv2=#M?K*tl5P%mf_ z(;-7~LrK0CtGrp}imQvb`I4k{H8>p!3qss5rPn=WMXfxpQjyy|SEB@!XTzyE(=|?D zMT>JHJ-4C_UCz7$p?}5&j|8crKi6P?l1~OphVOtrK<^fn#XF9V#~+^CsP$|=*N4-r z&eK#8KlMG#ws`0B}d4J2(PrWK*e5T!*dcLpJc^O|Fx5N+Zu!|rh zT^$+nJ~2H4eIjZ-X+QtH;7wT5x+w`9WkDrqSJu#uGRS3M<3`8 z`yS}Z>DEY@j~TpcE0ej)C;rJ*gd45gC!?EXCEhZziEU3>ra>yuMIxuv5=T3P)Au&P zQ6lzn>uE(a1SJ;Dqr5n?eo2O|u6NR>cAU2MvOS0Hb2=jVQ2cQPv%%$1aoGi(*GW>( zZ-NSai=4;ftO)V};tAgajv?@GeTH5oTBnadwI*Q88~|;3wkZ$YB}k+hAl#^seCBoZ z%;~Mv<0J~Bn|hY1M#Z%yrMw&C6ka(IsR}!IieOUTESsi7uyB==7>3V z!sA=p)q{>71-sH${0J0iYJqxDHlA)u;*$RnwY%~x>buwK9D}f)vMI#s%&}O2I%(;> zb|~EjN!{r{tBfI9*5j=U+vV}!gYj#q&q%r_ph269ZaoH=c!@J@I6#)^2b`V=p{w${ zEkZa}Yk3G~p8Q5vt*rviu_bE`z(&mb*YwiD=a0+a$UC4~AB`9WoV)8aqmMy~Z&vZ3 z8#n14@sTglX#1x5?O`NM^!R*SUj8u-&+De=)&qxZ-X(s^2Juv9nO{GCCoLAw`UdxX!X z*#*ec20%Jb^Buko-Qwu~VvD6kjoo;*@Rrt|5-NV^V;mMVKxV|#xEt`LOCaWfvT=2}(_A;__kpyD< z7EL%IO3(9AuGO+x;1Ttf^xRuH8T@Yjs;MTG=0g6oD?M}1gChH2`<9*{+=UzGI zRqj_641%yD1x9IW^oDb!zijkH=da@wpsfF>OL=v-Tc+l_0)rUNS zD)&UzHeyDm%lIqo3#EoD$n;EitOxzGCA&XMiJ=DD zhNL|>1wX-r+w;}7s=FK~p=I5IN}4SX{>{|xzev)2@DJWi@WO$sJ!>_XH>{^D#{AsK(A`O zaOvdkI`MS!dI&^nUUF;>03uQEQz#_8I zHI@78kt+gwTm zjjrom{+J}fwgY-@4)!=fVhydM0~727vsG9hnGb6FEOUZ`?r9Z`(FqsJ&9{jx_eqw~ zK48j{6uM8b9|;KF9s&2obga8=pm{fE(IWJe<|&8Ds67}4qHU5@i1@HAW^BJzUz7`z;vhfybj96YKTf&9Wt1H}~BE>)C>k61)8b?uc0(0krR;HeT|(0HH`@Z80N) zQB+Gcte|lud~fh`KM^8&=mcI!OWxx`o`?(ASGS6{t593Ny}n#B6`!Mya6BfvwJt1f zm-BOqHh9D<&~s?$)@6E8+i{=ubIpCS7go+sx130~o;T0*Grov+RGu_@ADhwWtCQ-r zne62|k|EwCOzEpNey)#gIr90lcC@2X@{6mQW{HV{Akav(@1a!#!ZWNLXirRpCR_i5 z#q@J&8J-B&`VtRIpB*mD0SI zTppSt;%Y5qRPi z1GI@%uK*HnUmVGYPWp30?fIARqP_#=|@gcSL>-aWnf zH354{XXLx0{FEcx8+m(dJW9KYMlKLebjdUqHLXl8b?-;7-|W=Ed=!6Fb-XxdNcAd* zXf@_B(>^0AyE_GlN{~kZ83a+Xv!BL=?j~%##+i0_NeUrNpSJTzS= z_+*8A6MHrSuDGEl+ugkTD*I##&Gh>3;3={8Tc5gqO;**(Ne6ApGOX>g_?d{zf{<~-lBA7@7tBDG$l4n+Sgrb4Hnv5U6GKQ zIvKzKMo=GeKjKJxGG!!U8#G-2QMTSLhlun1sL_=ku&W!kY7KeSQ-_sA1g>H`SA^O| za{^3HY<>cyxZUWwMd*bzK;Xe!z2EO3OI~gkykX=pkNdEV)78aY^iq8SZ`CVHHY`xi zj5FOQ$eWcBaRC%?IZJz0jFM2>MY*VUbqaGaK^HE)OTwFfaM|ut7iMIugqqwQU+dQ? zV9`4nq}os)x$?}+H1wsIot-ifufaaJ*o}4gxuO8#<`J-bWI44_g%tKoQrD?jA*P~L zm5VfHCa?DXEQw%~YHQvdWfA>+?}FF?xA8RRp|mdYf*?xx@?jaFXEilb8Ni-KN0`yJiY%!PV`N0NnfdcV>TUx6D^x4r2Fo~;$Prd$Xt^8JPy96@f z>401_>mHHQKDP4s9~_5c1)z$MbwCBmnE>4saw1agh>*lybeJQ0+JbvKKC2VSzS6m| z?wnHo2Y<-&uNOHc38_#j3T4k&<=)Pb^~5d106uspP`5yD7(TJgSwpGEw64V8{mXIE z-`?`q4;8QOWSykl{FwM!_#@S%L$!kV zv{oX^1J(jJ>^tY*vWvCIk~6r@z2TyC6smj*JDW1J?Uuew(>YI)*V*a>9NJB0UTEfN z;?_wO#w0AR?}QtJ2HtMfu{IcIDStU~q2`j0AFWr*#x0kKzryJW$uGNo3gHEk3q zO!ku83gDLX&*M&U`D;)2&&=vdP5Hg=@W)=lTCWOv#(6RzQA_G9EoL`%@ac!d4VMkL zI?Biqg08t~YF=5R6Cuhg&dvYUP;WrV#YvCoKc{9o*lL+2uO1zluDMHkA;kOSs(Y*J zRTkvXEdtBErR6hU1Jcfw7omD2RU#S=nm9ghl1o zO?<_?LOrs7Rb98L1JFiqF*)f-`~2lKNPbQe^uP*fCdkPo=uMWiR$AKtoxw$jxL$jL z&vMOnMyc!PckagsFq2b)nTwm*U{zDpSQy+84%plHdr*?wG!ysfI-1_BYPRol=h4&5 zIKSer{$E4%wtr}&#-cAY;8Kd1)7u?>7L`!9c?5SVPKEJ}@~Z9Se8{7m7-Kir1Nnvv ztCnLXYC<54^qnoU2khdE{-jC7&7cnf_aRlIcvXYm&$;=YZ+Fs*69 zeW-j#7o@Des>e^PQ}}g{BCRxHZa+##Tha9RA)B(^QLZO`+i7VCe;NOK(;PwQjxO|2 z7z>M@YxlrTZ!`0mSccbEmI(_pynT2BPK!0JyhXUCJ5^*R8y4#S!g-5&QllnHIOV<{ z3B7cM+gUhj8*NjsK0}W$q%Xgp^OPDEor+t29>qR+MNeWhB*%s1XI!qhj@bydW{5ek zh#|6jk+(~b@YC2h9+@$h&gjdAa@KBH7Lg2Xu5Yj6iiCh&h79V=Ivx$#s7ALNHTQOk zFq16HySLL*-O7tu(`XCk+@}SbRR&sXs+EQ}UWye9Tb*~w!W_?bcJvsx|XMH$Qnj)tz7^6iIX-mz%r0o3r^BKKY6WNAz69a6;YII=iTEhxzVsMRP zPunGOcl$(Stn_>P`sWBf7~|NpP&gp-kf_g`<1Km~WPT zs`4e@l(2&pmu6oSYlx&>;K;}I=wxefz(ZW|0W&K-dsRQK)^Tn75H8Qx?7er1d)I@UI(ZY-#^&<9l@W!+y^=b|_fvFMYo%x^ zr1Atts#6j+VZOHDk@&l#Xmg4DH!?tBebu-|G7Vlhe^Wb19g(4#R24$>>`0rKE}pS} zb?>Er0>mjv=yxj<^!T>!n!bv>k#>acM*JcCNTcV=g_DVtL=9WH>dFs4rjR6zoq)yS z4oH~~O*beWb6v<9)YV(8>lR^(+ZT90TTzoDv2xf~R%`aUnP5@lTPNWEg7MM2y{AQv zj$2An`xC%I!;w`OS?2xBQd#uWc)Q|f+>c_k6&&G}gk3tlBv;7z1QcAN;oA@4tUS-o zQt(PNdK{?1_%FJn!+?1iX#H_Ps=em?oeejV`xcQDQXcQM^*LRb`OOhp=u5c2wXJ}m zd2oL=0CI?0?q^K77bQ)p?Eky-_CG$Kzp3U3b}- zc1x0#*H-j-3(T$L$z^;5T>$Qro+1tmUG>GrfNnI{mT4Wmkc) z7S63$dfroQ0Li^C?H#-q?2prF{Jd@@Re|-H^IxF{lI>{d1i7-Im?P0|UOc^uJ%Idq zdpjn@&BYm~mK$gFVu5M&aU0Tak=HWO+O$BVgQokR zG|}?b!I$x>_RzW+VH#lyI;zTy4{gGF6TE16(y37%7$EARL0P7T!l zk(s*DUQ&ikX&5r*Ymz*01azu)Al@3QBlu$qHuU?1zeQC;!dsOpw9$286EVfqPj3w}gyPFmK)exC|o5AG1r(vy-4IrF<3WSnZp!87e z+Uqr<4YYw{Ept^PnMthwxF1S6i&Syg0bTA75o0ba14;&}Iq~JC&fj-H_B$XUcZ@Sy zXMq_C1b?d94Z0XDwrPi(Bu$O?8lrIADP+xJ1B<}Ag!!{KCtE#c&}he#MUcveyf571 zl8yTr^jLd5CECHCL+G<|+i^!f)7-wRbq@739x{@$W*n9bSASl?E%BP7Fb=(nmRpnS zAjbFk;<$}xEB#}Zi-fHb?6Mpj&2N>e&W~cSU*|Wc^2eVk6HTmQZpt1K+28;;Pyg(l zJ#qi!o$LPWosZ-I&z|unGVBr0E%=~)l?+GgzF2JaL;HmpF&7JZ^A6~@ZojgsjCB@1 zl0FPn4}_n-9k(c|%f2|b3l2>pxyL`2cNH|E#N?~?o-(iYVT=RJ`mV4hu-_Q4&LpSlNK~8b z@C>t~y?l5O{RCRTS{qpZw1tAEQ|%CwIo?tcWxaATMsJJ1B%K%yRKSa!eegCwm%~HK zk*4aZPWvGx9^e@XGuIj;XEoW8 zp1gJ~CVj-}%$ zO~Re~Q9S#)I_{KH!zsOQ6#Dr*DvefC{`zo z4sV%2T9{PzyPfGRGc$Lt7^sdI)nkF4fL!+0sh1n&roFQlZ;NTIlx%Gs)Gv;cZGZzt zq+J#eK`B5NIB#VVwAT;D!D(osTH2qg-~KJ+nX$QhJ&X40nSL!nHj58czpuY;rM0FN z$B$W>*myvw_!7>74Rlfnj*(;LrsCZ-pDDg!JrjwFR_v?N+)RDru>&%Gwz*{$sFDxE zJ!WzX0~^i`IBcOCtU-WABw+(o<=`tJXhT4mB`k0dZMK1mtVcu8qzgUJUSI}9%>JY$ zXEffP<+dH!Jp>-Z29Ip1vE1=2BNd=UYY;afnOgJ-K7plRzoI4j)(ohzl>QYpYpe$<;HLSf;FdTBL0c-mQtFr2|W|*AE(ePix5a zyW_r~3e3~>eq4VcN)UR|O>u)6mcoK_b6de7Zoyy0J6sJA#_1>^Vl5&`kXDimk5LcW zh+za0E7>Qt@8f0*{kQ-VbZQ-m&DGuk5#ndXxgYzU#k5${ib`?Nsi-WwxGQD@(R#Cb zv!3`S@j*oIm!s=YAo)##e6mN71cEjflIPCv^7%=Q;3zKR-j-R#S+6k+RHs=r}wDbsMOq)6-`6nTBT#ZuJNYK0K4b4BG{{-3}YFA~4djH9g{U{V>p| za(0X0y2M4b+I(t1>pF4Ua}?cFPSEW54QgXV$B$Tk{%3~$pEhF=4y^#xh|B@Ea^4%h zaCyJa=jl2`j%hB!sKJ7`17sgt z^0L?A#F?`(i#5ZK^@HxygS&~enDsOILK4R84%tb(=*d(0+?&tZX~V6ihddX>{l7w& zEQ_4*_mN8xC2f|{i`vwzu7p^=N z?w$9q!782%v^?E`=^wjvDOEe|?oDCK85{{sTFjuFGw-|lvR^;+PPAXpExu6Y>v?L& zoZLYssRnflY8;=6or~)`f9`FqG@Mpznj+|Bt3Fh#8tVsKuq64_1XF;NZ^!9=1ZVli zPwueEd6bu11|=2td29LN`H1@~SlKA1EZWJI#It0LUR4wZym;JA71p(zJD@wBrmP4r zcw2BYeB~y%Ic5>;Hs`}Uga@E?QVj5Ulrg&Z9=fwVpZ<}q&yqyHkr;sx`?gG*QBP|6 z{bSYVd<3PDYkn19PJIlEl{;0~5N5b?bhFym-hGgnqoEx}Q(zAZvU}N|*~nGijU3Gu zBtQK^xCFJWRiP2ctP;xhzST!|2X)g!y}s-n6*rlB-^?a6FR86jtwK;*fIBLB$H`+v zUV&D8FIT<06f-uX%s*&%#2M$dfH3h~6#Hb_kEVs;MxEhv=Bzx$&YI_>cm{E!ol=Yr z8{e{0q2s6Kilh;tixYPVJ#N|26Jv%DzFFZLWh=KFVF!fiZGQTLC7rY4x~q+eS67K1 z5H7Cr{dmO@pFn#b#^|QV=D~?tOM5;`nPn+^H1s0XqtuF zaz9Bm?Pl_-S8FJ``HQSE>x^Qbk`A@zjXgaYI#XD?ytIN^f-OUx$JMDmKt}e*{KT{z zeIti;eHg>orwpfGtXSiI#031_OJIJV#~MF8YeU;HCHTLtUimv$F8aSPMd0t3WEJW- z3|!*T8b5rqaZI0i;$b(D zi@5fPu5Gz_pF#BZ^F%8&Putj&RJ8OCNLG}}tk{oqKQQFtvvztwsu+ zwA#f70=g04*X4=ZtcG^9TySua99E_7C$EEwgnC{FPV>oTKQ)HB*>?6IV$Y{2e0b|9 z+e*fH_?oFk@F8@RAB4~&hNiTv@p638IHE)PNbetlW2w4bCHkT=^LpZI;%lmtQ_(Kf zvm*z#!7M;L0erWlni^i`@7=bRz^1nBslz^K9?XpMg@4>)oz-WXnH8QSOrbWs1`#eN zd|a1{+M!bD7Yu^eZs{Lg^GqjhE(Ja#R>L!}l)c1)oIML>ETXFaC)YLnte|eZbwh}F z>o*oBx>*#=Xn<|~@EQ9ve|y;bPoU+c$?ZXCpId*L9>kUs8gcEnK<9624FgVx32dt1 zsw3on*P0|JuRxBSA#JOz*?e zNwGVTAIc``pBdi~Ly=%XzD30=bssuYp2)to)r99qEsc0Bacy4_ixKh~Io_D&Ohx5P z%?&Dz+Hn{hx}smd0 z^UX&S#4*>O-;Q$*zLk4N*YzxH$Zn?0(L80)o8!S$AL(`Ot6lr!ZimO26^Pn0sfhQXSthlDVf^U)RGsom1Fv*IYD69?=rF`*U3D}s z))3PGD9XeD-iU*+(dLuqag)C@_`~gvMv6Os+L(;a<)6B$ZQCjX&}QQaY^N~Fo}RHv z_ZvBPEat}r1V;tRf%Rw@!3$nCjp|aW3EAy3&5`4xCRKEW$v9qfQ*(CPZ|Lm$W5(wM zE)gmGSp*wnsj46zYWm@X&TdsE;dS961(&2hJR|HJa<`;O43I|YiT06DZ#kp)Fe)}g zoFS}(ujm0!F}XBR+|1`yKU(8r8Ah5h%D=-+^6q0yfp$?-zrYN z?{H9X_BaIeepA`2>3d(_jWGTWzK`;qy}&Z1KElN=B!#WY>ygsm^QiG-!SCQ_rUc0j`#Kquimg0THhXx!s%xjD#E z*9i=Tz{nm7-ug_WS}R&ExNQP;1fW*q!SAQF-Mzex)ke3g;N+yPL*ur9y}K`Xlj1n9 zS0l-)*bXe2CoHm{dCMPObt+yH$;cB48~~b?b{oB$KK9e}@9%p4A4*ZYr8WpnOKrn2 z5%bZRORJ`Q=K81F_B}HStq`gk`|5VeSx+%+$SV`;>wDPIg7xb$EIP;0w=FJ*ygSa~AmVDV&VhWzBcs<&#u|P+nm1!rkvl&!uuOhU zeg1$mQsqpAr&xg%BgJ2VCsJWb_#6Ejz0Q_0e9%%rGn9OS*H~!>boaK^wQGmDxOxSm zoec)N{PY&Y)pP{iCwO<7-_Ydi@3JU%#d8 z8_1lFo$9=p0oo6W>bV{Mm3SdFdv2ThpEIAFY9hTiogUcCi@4H0w&o^0HYP$9e{iY3(O}|= z<8qR}>galW*$L%KS~;)cd3cU#7QAA;SzYw5DCu2c#i))`ZE5Z0Qn4*QaYQ`#6W#Gq_?9lShw=mTZQG(19 zJz{({K&&v?(y+gpQ0EDD|6;3gC-_Rv7if_}srg8f>g$9yp3RK0latNv$zijp+$;}| zrip`O%S#SqcArwIS-fi~>3RgNlo&DgEOUKvH)?A)c)AmO>Y9H`IesW(Gq_2s74Q-! zTi7Z zOu~^?i^2|32^BY}3X2apFE^Twugs<5?YH%VVec5FFTQ-SlVP*UICY6=x$d3d^(jb} z-A88ur_yFtSNR)|ZZ$_&q^D-FEVJJwji@Ljm$1R|-zjUHUn`P;laFM1ept6JclW-Z z&?x@&{TIy{W2kXVOFrgwKtGu0aEh*ZKL$g`psR83}LpFkC2HGuYpe(odHQIELEM7i=f;>+MC|z zym*b5`Ksf|9p=LgRSGg^2%)AW5fbzB65EIn#Gj({p+<~qPgB!pRNcI${KeH)#cmhY z^s1Au^_-Ofu2u3nd1)|hv|;eMjY!nQ`*HTHji|AyX)mL1{-!k^2-9TcyI!NthJ6J` z`wmv+Cbapwy(Z3MW@~0zWJfkNfg}jcr-cp@dD*z%}`l| z{0*)HI4^bmYhBs>ZVRQ(qGp9zy75jOpR!O|dF>YZIdK`{?)a2fU=?=3LyheDb8hrT z4Oect>0`oL-JjQ9c)>}}M?h~G0|(IWJv%i%_3GTr35pYPX3D7gxA~{y9i|Qk1OS|< zVfD_gKh}!kEwy!!g`5GN?=uh??cy|L8OS2FhS9g7<9ByJBQ@IbGsw;)d(l6Zmi-ar zY^QUZ{?{2IzmswOnFI3o%bBW<`cbAf$O}1<=Ui7)eWgPRPDk0j(9CVP7a?aj|L(<} znenAmbP1}nuEa(Laakl;P|1O+-bnT4KX?E8zBgSufQNd+O+LMl@93yxj{I;{%HW7< z6rsLe`h3=|XSj$5etN@E3##}4o)Zye-iXu?s&n6LkcV{SeH0AWU0P$;Vockmf9_@V zJ2SDDcM?Ng-@R@=d-p)kYSFzOZ&#P6p4y1Z@_QQvV(wK$^%bEEASd@Vp7h|p&-lq0 zFQzTLEDV2p&GXQH$t3g#DY;YcUU6_Zg*PeZxXfr|u15=HL|k0i&*uF!*RO()vaVV= z>d*=bXTUWmfn%cdCb{%Le9KjOjft(UUmKd*QmW zWR-3enrd!}jN0Ffv{&?}5M@i>{`4_9jbHk$H899vD{6tf#OGyeM9 zZmCV{f?g_B<359aPA;!e!5Jp?CuO3rDkh+wM*ifb<^Ex{8kMpW^3y;@d-cngL#{8) zIJQhJHq`DqX9)TWjG9jRw5oo;l=G*JSv%Hi4^G0yokQ?YaxJckKURU%eB5NkUyova zBpCO==r$!6gQ%}cm=2zFOwCv;%Vy6S_^H2E+TH0ySgblJkA8~jg*>2HWT2qECf|r_ zo_Lo*x}wID$V?tWJUOX;Luc#~&xpliN*td%@@5vg-M~@dDpz@qrPjq=??y7;8?22E zDX2Z&^v+vaWsOdVZA3;wJM*|p8-}&YY#5phD4PULf-%*l-Uz*U zEYN*eEuwBcHUf5djb*^sx!k`oTB2k1s0(9C=9l-NtlHwVm!L0XW zB2#b%oeYgdPo!W-x<25NwJKJSO$(R`wB|JCqGt=C(-eKiAR_}H3gen17oqlZ2qGCn zF$tzT+GWXpy}Tx3oD@=L5cS@OKgTNyGoEBcT+i5xV{2d&(c^e5Z9_UW>9p3_!o`Ee zg#CYkP9^IG%ia+k@0goi&e@th|J8VQIvjRG!?~%S{!;SZoJQiph-JbVh5f=(g@-S} z5kiZo;5&lH8~pku-XWZ6b2>e7NIt@6vc;Jst=(N$Pwzcr(_n|07`@%~o2}{yJq}OYAt2mYe1N|T_m^@ZZyB4;^#lGf6qxF)Fro)*);qv%z;hM%KuPE* z+DxMzL3CVCGw5iVc(}cXz?66-PVEllU+sUYp}Y8~(`oNXUcX9lbRx>3l!i?xtZvB4{4{KE>OjdJ zu8Z35osN8*RrfqzuDsmubUF?c;EdG>5Zb@EWc|Kbp|w#1Of{xGz&Cb|I9S~`J*L7N z(&f+}&mncRLhjZ+cK2J79sQ5`i&-6YCEpt2HuXMguR4WCECfqPXni>0sxXB`xgyFN zt*kpqJD`J1%d$L)2$+f5nNaPcn-#j9c_U!Hd#yl^^b`IRiErbR;sS@|C2FTMUHa@A zE^aw7iJxc@VOci|iNg+kS4u3eN6Gf4+gxV^8>bk=!_H~zP6FM05Z99bcK^Iipl_5j zGOQ4QYQ>xhP`$W7Uv1B4Sm* zMUSd_0%hXo=*>6`3%H5Oz;_GK{FSLR``3WX;NMQV{LjV&8|X$fBdwCLqpt-QT`&_-Y-@k7hv3|{}*IzeX9NCWcOjxk$jKj&d$W{kG@#V&w9yCfI zMMXVOEp+@_K-2$dg;$R=w!495-$!`XZvG-h%Dt`N&#YYZcfih8_=d}MZD%O8YyC$T z_^%BJce?&Z1%1E&HUQpRBnt_Xc4~X)S*V2Y zSH<2~-_TFrq(ZqU(2_M_!7nhejZg44>}i!~FZzP0!6jsq;!sp~pinpS*)U0qsLbm0 zhEFN)6`N7RkNEm?jmr|+==>9 zcar%ke!gh5VnduFKU9-(4rLQ(iQt-E1xFMf%aCsoJ5}#_uj{XynBO~Ke}0nxr;2QU z!(!bYHtH|auoeq6si~-p058TN(lp;3+0^1Q2+V$H*Gp;#R9JMmO!SJpsP;0^@e0?C z6Xu0}C!5MHC~|UpsH9U*YFR1XnX#b zMG^nCLD#?9ME{e|RQh7!&rczRMYg)u<{pR>QlUu)VlMZet9y>fsslZQY3_%Lyfrss zNq0hLNdPrTj|adU&5{}6?}6T;rr#t?;@K8`HjA$Afb!p9nc_MC_1WfMeEO8z6W8D? z!Myij2Q+gEO3w#RJu=;jgRMq0^}qV1{_E=kRa7x2Tu(7NGk(^JePn6H3TW;&m4{7?Z{WrG!tm!P|=zU7LXT-57aVl-%iI8x5x*?zFQ@U#_5TluZW_0R z%<;ygtqWv;fBiFYorep?LByq^`dNq5tF2 z%;w^pgd3V=7PC1tZrtgwes9L!qt9=z{M2Y(x&uu>ZY~RxeBNVQA&jTo9#y?CG8m=K zQDOO~{}yH+DO@wA2NN-Di>AJLjJhR!z=m|qZI<=MmBlZ^&DYo;Y-iNUu6sxL)T;mjVPB@Bu_~PK*%E2g~xyd3vA2&0#l_ADkOXl8)s!AwZB_r8k)RCie9Ic$!*htiD3CO zz9pdhQ3~HoTyqIz32gn`0qLaXv5Ej-LyjylwnR690DxxxL+~=OAH0ef!p_ow$y=-k zNB}K)V?%P=`h0l@#L0C3^|fD1@@tp;Iyk?K!Y@1d%XR#6i@zcTiLo@6)=XR_G)bM9 zJrgB!p)*|Zg>#3Axuy|&}Vj{)4$8VGwb6`gj(9J1S4C5o1 z4pw3GC%~zmesHD*GYGmF1Wm@GN0#WuX+}V+B0GQ}0TSRzD*yv884x3!CC81wGO}b!>@Dk%Rc;3&#|`7-dx*F`Q&reMJIV4R&%2*fRq)|BG&@2l$nlhw|F)PxpAq|14^rRFfN z;?shGMqb?JU>(rj0i8)1UM1dTJh^T>kBMwI_aC`7_-||ce<2zCuLC0frYi&5IZasl z4S&iG$hC;BKp*r2NO32&xVHv&K-tflv7KPd*p{(+Z`NP9+CMlW^}khR_xI9R#8}`C zND$Cj4hm+8DDss7(s>?eEA(R6ReEf{^8A0y{r(5|^fr!a&oTz90(vv~tQ)o7R(oK>C4joMg(@?UD5TENnl-00fXv>nj1z5-x|?IYSus_EwEc-G60zcoZz z9`Aq(fzfsqE&p|gVufWAbb= zm$DSw%>TlDA@=}dD^>vmVgbO0&-Ug6Dt5;q=?l2`;N=hKMXL<`)!OMc#mK+NX8*f9 z_$$ADi2Nd(pqYMBY@PzR9&b3};DwpoO)qiT(BCgp=6i_)k2>bf>k-0xo zF>l?i*!sgnnvuHzXCo1NeG0N+KR9%kR3dwsmXk{AI@7;)jQV=l@U`PyaZ$kt=#${k zatS+|_LOkFEQbs2X!H9X`rnTV3?~jx`qRIheEk%|EsM#2^le%^`CNHH zmgaW>l(GJS=Yg?>H(W9U4m=xP@M*^kE;csgz9^;~=lM8-K@4CdtOvJrr}i38eS=cO zandq?PywT1A9bE{ZwML`J$kU}MKm<%>LF4Bt7Q>3oO83};E-@@MA+G%M^AEAE~ zK)~99QAQ<_mB&grQs!&F#6?+@iuEPQo*t}2KbbM_@G7+1RvsKEi%w{k4Jc?_S`@7+ zDP3uW9j?p?uo|2hLMNT>UOFBWvp2g_x6D(Q*NMl-RO#~Y#Fpo^i&sv*hIO5WAEZ+s zzuNT#0Uva`#`ukI;ywqoxKp!nU&dAXp<}qRJL9a?rSAB_EkC=u&uD3PM$x&Y*-a!o z9cMQFXxtyciVw1TQ}-|80jq7g9$i3%tR0_+sHCnudQzZtj){0)D+y4tH)xQXku@Cp$@Qi!B^Tl5-xkYS;O$s?6@8ajLOM(Guoa z(Y5|`T%l3p+j6$MLE^vLQNKeY`cFqu|L73Xf2)wt-_!BJp8%3qh6p*DF_ks3curj+ z>8(YW$(Q5*hrRa>YqH(4hrxy@5)lQdQHp@{A{`Yk`cPp zj<({-vJXPdqNJqU)9bA|){B(u??XYKP3nPZJN6PFe%wJ+R zaC&iVt){vy7adiI> zg}j*t#}avn^X61~a|Ynt+Y zcY(%wBv)%f<S*1A-Ol;$iRll|WbbHUN<$8>ZoqfHn+0or z%qKPBx@Q4fk2oYM!R!@0?VaBTE2g8O&dZN9O_n}ReVxg+XN!3F-oJQa-QPE;e!(9+ z5JWk!{5-@?)4+LujpFHnAMZvajR*8_dY2z9n5nxDM4LI*ARR7{hjU$2#%fd7#~rN4 z?%D9yov7wU*Mx5N4Y!Lcs;*{G2Rh_AQ5=!b1}oP4tf}f;qrKO(^3~NX25CGZS9&kc zpS2f<+Uf&d|YU{{{P#U%J1Z3_+7=sY)h{ZP-B z%DSWuEdar>6tQ*t%{Y_#E9~o2rkBbqop{2t4E5AHza`+^^7GcCD{neBme>W#fzK|D zT5KPb|Lb24;zTPi~cW_?HXnuX(EcXUZl2tCgvj5{|i-Bok3G48DJ` zSpJh>{TDLFKlv%l64A#=?B5klaaYXq+N~bDc1W!duzh0fAj@;}8P0G$qvCsyXNDfw zadxxXVZ!v8L-XuG=mj7Pmt5-K4$CO9t=5$eNMha|&b2Gahb%p^fu4{&KdHor**jCK zJ)*2g`RTMlXT_<8tH-Sm%0dUpzEI*rL|o~Lz;Tg-!J9kH*|b~KPFe?1@vmJ%u2cl6Aj7Jvn^YSF=3|-JZ}jyIm8Fpb%+Z6n2|pLMd=PVocjQqU z{3vBrh$7_1M$iP+-mPGX>t4IljoMFaYGL4Tl_v@$IpHT1{QObJ^|6BD%Zs10)h}|&Z=Hn+)ZbdBfZgS_K!&B*lhU9g{J-pul+~dku2!;zy&$$XB=6{_wK$b z6g+oPqvc`%Lz>f-GM`iW>n>Zw=3X6#q0FIMkG-#KJJcp`+;?(gElAlABv_k8pf5n5 z+|)FO*y21H-tTzdvf##gbhvIn?KtuYc+7r9B#hX))$OtZLasNA3QgkANj;o4lRQHc z@bz-d&uY=UFZP-fjXcp*9rx>tA)C&WvH6J~QQysv+oy;g1aG{D2`RfNYFyv0Zn#)* z&!uCe0L@v@r8T$s$t=B&u~DvgbUl1OsKESX7ofJzuiG$+GodHd�y3UGd_+`(5ga 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

`s~vJT_p-%dOv= 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 KZ Date: Sun, 10 Oct 2021 09:38:58 +0800 Subject: [PATCH 204/334] update readme --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d74b09be4..51b787586 100644 --- a/README.md +++ b/README.md @@ -226,8 +226,23 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
+商业版主要更新 +------ + +1. 兼容最新Android S +2. 不易被杀毒软件误报 +3. 框架优化,性能大幅提升 +4. 手机系统及APP兼容性大幅提升 +5. 完美运行Google服务 +6. 支持运行纯64位App +7. 内置`XPosed Hook`框架 +8. 增加定位模拟代码 +9. 增加改机代码 +10. 其他近400项问题的修复和改进,详情请见下表 + +
-代码更新 +代码更新详细 ------ **2021年 9月21号 至 2021年 10月10号 商业版代码更新内容** From 8786684a6111ae0712bb398d40febf729c619c92 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sun, 10 Oct 2021 09:40:38 +0800 Subject: [PATCH 205/334] update --- doc/VADev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/VADev.md b/doc/VADev.md index 109b24211..f2f07fe5c 100644 --- a/doc/VADev.md +++ b/doc/VADev.md @@ -4,7 +4,7 @@ 第一部分是VA的源码结构介绍,这部分是为了让开发者能快速了解掌握VA源码框架。 第二部分是VA的基础SDK使用说明。 其他更多的开发文档见:[VA私有库Wiki](https://github.com/asLody/VirtualApp-Priv/wiki) -VA产品说明:[文档](https://github.com/asLody/VirtualApp/blob/master/VA.md) +VA产品说明:[文档](https://github.com/asLody/VirtualApp/blob/master/README.md)
**下面开始第一部分,VA源码结构介绍:** From 179efdf3e5cfad4c310e217a9e216854999142ae Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 15 Oct 2021 17:29:07 +0800 Subject: [PATCH 206/334] picture speed --- README.md | 4 ++-- doc/VADev.md | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d74b09be4..f465da33f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ VirtualApp(简称:VA)是一款运行于Android系统的沙盒产品,可以
## VA技术架构 ## -![](https://github.com/asLody/VirtualApp/blob/master/doc/va_architecture.jpg) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/va_architecture.jpg) VA技术一共涉及到了Android的APP层,Framework层以及Native层。 一个APP想要在Android系统上运行,必须要安装后系统才会接纳。安装到VA内部的APP实际上并没有安装到系统中,所以正常情况下是无法运行的。那如何才能让它运行呢? 答:那就只有“欺骗”系统,让系统认为已经安装。而这个“欺骗”过程就是VA Framework的核心工作内容,也是整个VA的核心技术原理。 @@ -34,7 +34,7 @@ VA已将其内部APP的全部系统请求进行拦截,通过这项技术也能 ## VA进程架构 # -![](https://github.com/asLody/VirtualApp/blob/master/doc/va_process.jpg) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/va_process.jpg) VA运行时有5类进程:CHILD进程,VA Host Main进程,VA Host Plugin进程,VAPP Client进程,VAServer进程。 VA为了同时支持32位APP与64位APP,需要安装2个包:一个主包,一个插件包(在本文档中主包是32位,插件包是64位)。 2个包也是必须的,因为一个包只能运行在一种模式下,要么32位,要么64位。所以对于32位的APP,VA使用32位的主包去运行,对于64位的APP,VA则使用64位的插件包去运行。 diff --git a/doc/VADev.md b/doc/VADev.md index 109b24211..93ec0cb24 100644 --- a/doc/VADev.md +++ b/doc/VADev.md @@ -11,7 +11,7 @@ VA产品说明:[文档](https://github.com/asLody/VirtualApp/blob/master/VA.md ## 1. VA源码目录介绍 ## 下图是VA源码根目录: -![](https://github.com/asLody/VirtualApp/blob/master/doc/1.png) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/1.png) 可以看到VA一共有4个源码目录,各个目录介绍如下: 目录名称 | 作用 @@ -24,7 +24,7 @@ lib-ext | VA插件库源码所在目录 ## 2. VA编译配置文件介绍 ## VA的编译配置文件是VAConfig.gradle: -![](https://github.com/asLody/VirtualApp/blob/master/doc/2_1.jpg) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/2_1.jpg) 配置解释: @@ -42,18 +42,18 @@ VA_VERSION_CODE | 用于配置VA库版本代码,开发者一般不需要关心 ## 3. VA核心代码解释 ## 1. `com.lody.virtual.client`包下的代码运行在VAPP Client进程中,主要用于VA Framework中的APP Hook部分,完成对各个Service的HOOK处理 -![](https://github.com/asLody/VirtualApp/blob/master/doc/3_1.png) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_1.png) 2. `com.lody.virtual.server`包下的代码运行在VA Server进程中,代码主要用于VA Framework中的APP Server部分,实现处理APP安装以及其他不给Android系统处理的APP请求 -![](https://github.com/asLody/VirtualApp/blob/master/doc/3_2.png) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_2.png) 3. `mirror`包下的代码主要用于对系统隐藏类的引用,属于工具类,减少大量反射代码的编写 -![](https://github.com/asLody/VirtualApp/blob/master/doc/3_3.png) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_3.png) 4. `cpp`包下的代码进行在VAPP Client进程中,主要用于VA Native部分,实现IO重定向和jni函数HOOK。其中: - `substrate`中实现了针对arm32和arm64的hook - `vfs.cpp`中实现了VA的虚拟文件系统,用于控制APP文件访问限制 - `syscall_hook.cpp`中实现了对IO的Hook -![](https://github.com/asLody/VirtualApp/blob/master/doc/3_4.png) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_4.png) 5. `DelegateApplicationExt.java`运行在VA Host Plugin进程中,用于VA插件包,实现了对主包代码的加载执行 -![](https://github.com/asLody/VirtualApp/blob/master/doc/3_5.png) +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_5.png)

**下面开始第二部分,VA SDK使用介绍:** From c7e8d6a1a644e04217d820af2f066d310b9235de Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 18 Oct 2021 09:21:10 +0800 Subject: [PATCH 207/334] update readme --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f55bd8dd3..01df67df4 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
-代码更新详细 +2017年-2021年商业版代码更新详细 ------ **2021年 9月21号 至 2021年 10月10号 商业版代码更新内容** @@ -269,6 +269,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 341、编译脚本中使用cmake替换gradle task
340、移除过时文档
+

+2017年 12月 至 2021年 8月 21 日 商业版代码更新内容(下拉打开) + **2021年 8月7号 至 2021年 8月21号 商业版代码更新内容** 349、调整优化gradle脚本
@@ -468,8 +471,8 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 216、修复数个64位分支的 Bug
215、新增加支持32位插件的64位分支,该分支支持32位旧设备并且64位设备在32位插件的情况下可以支持32位旧应用
-
-2018年 1月1日 至 2019年 7月 30 日 商业版代码更新内容(下拉打开) +**2017年 12月 至 2019年 7月 30 日 商业版代码更新内容** + 214、改进 App 层提示信息
213、改进部分编码
212、修复从宿主向插件发送广播的方法
From b6dc86d657e6d17606e2ddb0c2a6ae87419796f8 Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Wed, 27 Oct 2021 16:00:38 +0800 Subject: [PATCH 208/334] update --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 01df67df4..bf8266b26 100644 --- a/README.md +++ b/README.md @@ -245,8 +245,13 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2021年商业版代码更新详细 ------ -**2021年 9月21号 至 2021年 10月10号 商业版代码更新内容** +**2021年 9月21号 至 2021年 10月27号 商业版代码更新内容** +361、修复抖音极速版兼容性问题 +360、修复readlinkat返回值精度 +359、修复从外部安装app,没有引用org.apache.http.legacy的问题 +358、修复华为Nova 5i, 64位主包兼容性 +357、修复11.0上外部存储重定向问题 356、修复11.0上GMS登录问题
355、修复11.0 部分APP读写sdcard报错的问题
354、修复va core进程死亡后,APP可能打不开的问题
From 543807d905fda7c576789ca42360b68a7c1b2006 Mon Sep 17 00:00:00 2001 From: Rover12421 Date: Wed, 27 Oct 2021 16:06:24 +0800 Subject: [PATCH 209/334] update --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bf8266b26..5562086f0 100644 --- a/README.md +++ b/README.md @@ -247,11 +247,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, **2021年 9月21号 至 2021年 10月27号 商业版代码更新内容** -361、修复抖音极速版兼容性问题 -360、修复readlinkat返回值精度 -359、修复从外部安装app,没有引用org.apache.http.legacy的问题 -358、修复华为Nova 5i, 64位主包兼容性 -357、修复11.0上外部存储重定向问题 +361、修复抖音极速版兼容性问题
+360、修复readlinkat返回值精度
+359、修复从外部安装app,没有引用org.apache.http.legacy的问题
+358、修复华为Nova 5i, 64位主包兼容性
+357、修复11.0上外部存储重定向问题
356、修复11.0上GMS登录问题
355、修复11.0 部分APP读写sdcard报错的问题
354、修复va core进程死亡后,APP可能打不开的问题
From af8a23f4d5d5cb671a55dd23535050045190dcdd Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 3 Nov 2021 10:12:07 +0800 Subject: [PATCH 210/334] support engligsh --- README.md | 49 ++-- README_eng.md | 702 +++++++++++++++++++++++++++++++++++++++++++++++ doc/VADev.md | 2 +- doc/VADev_eng.md | 534 +++++++++++++++++++++++++++++++++++ 4 files changed, 1263 insertions(+), 24 deletions(-) create mode 100644 README_eng.md create mode 100644 doc/VADev_eng.md diff --git a/README.md b/README.md index 5562086f0..912869fac 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ + +[English Doc](README_eng.md "English") +

VA产品说明&开发指导

## VA是什么? ## @@ -203,7 +206,7 @@ ARM 64 | 支持 购买授权后我们会建立微信群,有任何问题可以随时反馈给我们,并根据优先级在第一时间处理! ## VA开发文档 ## -VA开发文档请参考:[开发文档](https://github.com/asLody/VirtualApp/blob/master/doc/VADev.md) +VA开发文档请参考:[开发文档](doc/VADev.md) @@ -247,32 +250,32 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, **2021年 9月21号 至 2021年 10月27号 商业版代码更新内容** -361、修复抖音极速版兼容性问题
-360、修复readlinkat返回值精度
-359、修复从外部安装app,没有引用org.apache.http.legacy的问题
-358、修复华为Nova 5i, 64位主包兼容性
-357、修复11.0上外部存储重定向问题
-356、修复11.0上GMS登录问题
-355、修复11.0 部分APP读写sdcard报错的问题
-354、修复va core进程死亡后,APP可能打不开的问题
-353、增加未安装插件时无法启动的错误日志
+371、修复抖音极速版兼容性问题
+370、修复readlinkat返回值精度
+369、修复从外部安装app,没有引用org.apache.http.legacy的问题
+368、修复华为Nova 5i, 64位主包兼容性
+367、修复11.0上外部存储重定向问题
+366、修复11.0上GMS登录问题
+365、修复11.0 部分APP读写sdcard报错的问题
+364、修复va core进程死亡后,APP可能打不开的问题
+363、增加未安装插件时无法启动的错误日志
**2021年 8月22号 至 2021年 9月20号 商业版代码更新内容** -352、横屏重新适配
-351、修复部分APP通过file协议安装后无法打开的问题
-350、修复传递给JobIntentService中Intent数据丢失问题
-349、修复JobIntentService第二次调用无法工作的问题
-348、修复华为手机上某些APP奔溃的问题
-347、修复小米手机上游戏登录问题
-346、修复某些应用加固后无法打开的问题
-345、增加对关联启动权限检测
-344、targetSdk 30适配
-343、修复targetSdk为30时,某些应用无法上网的问题
-342、修复targetSdk为30时,sdcard无法访问的问题
-341、编译脚本中使用cmake替换gradle task
-340、移除过时文档
+362、横屏重新适配
+361、修复部分APP通过file协议安装后无法打开的问题
+360、修复传递给JobIntentService中Intent数据丢失问题
+359、修复JobIntentService第二次调用无法工作的问题
+358、修复华为手机上某些APP奔溃的问题
+357、修复小米手机上游戏登录问题
+356、修复某些应用加固后无法打开的问题
+355、增加对关联启动权限检测
+354、targetSdk 30适配
+353、修复targetSdk为30时,某些应用无法上网的问题
+352、修复targetSdk为30时,sdcard无法访问的问题
+351、编译脚本中使用cmake替换gradle task
+350、移除过时文档
2017年 12月 至 2021年 8月 21 日 商业版代码更新内容(下拉打开) diff --git a/README_eng.md b/README_eng.md new file mode 100644 index 000000000..1fc579bda --- /dev/null +++ b/README_eng.md @@ -0,0 +1,702 @@ + +[中文文档](README.md "中文") + +

VA Product description & Development guidance

+ +## What is VA? ## +VirtualAPP (abbreviation: VA) is a sandbox product running on Android system, which can be understood as a lightweight "Android virtual machine". Its product form is a highly extensible, customizable, integrated SDK that allows you to develop a variety of seemingly impossible projects based on or using VA. Now, VA is widely used in in many technology fields as following: mini game collection, blockchain, cloud control, silent hot fix and so on. On the one hand, you can realize cloud control mobile office security and achieve military and government data isolation with VA. On the other hand, you can implement script automation, device-info-mock, and plug-in development. Meanwhile, you can realize multi space and games booster. You can also rent the mobile game account and use the mobile controller without activation by VA.
**The code on Github has stopped updating in December 2017. The code of business version is continuously being updated. If you need license to obtain the latest code, please contact WeChat: 10890.** + + +## Terminology in VA ## +Terminology | Explanation +---- | --- +Host | The APP that integrates the VirtualAPP SDK is called host. +Host Plug-in | A host package is used to run another ABI on the same device. It also called plug-in package,extension package, host plug-in package, host extension package. +Virtual APP / VAPP | App installed in the VA space +External APP | App installed in the device +
+ +## VA Technical architecture ## +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/va_architecture.jpg) +VA technology involves the APP layer, Framework layer and Native layer of Android in total. +App must be installed on the system before it can run. The APP installed inside the VA space is not actually installed into the system, so it cannot run. Then how to get it to run? +Answer: The only way to do this is to "cheat" the system into thinking it has been installed. This "cheat" process is the core work of the VA Framework, and is also the core technical principle of the VA. + +**Here is the description of what did each layer do:** + +Layer | Main work +---- | --- +VA Space | An internal space is provided by the VA for the installation of the APP to be run inside it, and this space is system isolated. +VA Framework | This layer is mainly a proxy for Android Framework and VAPP, which is the core of VA. And VA provides a set of VA Framework of its own, which is between Android Framework and VA APP.
1. For VAPP, all the system services it accesses have been proxied by VA Framework, which will modify the request parameters of VAPP and send all the parameters related to VAPP installation information to Android Framework after changing them to the parameters of the host (Some of the requests will be sent to their own VA Server to be processed directly, and no longer send to the Android system). This way Android Framework receives the VAPP request and checks the parameters, and it will think there is no problem.
2. When the Android system finishes processing the request and returns the result, the VA Framework will also intercept the return result and restore all the parameters that have been original modified to those that were sent during the VAPP request. This way the interaction between VAPP and Android system can work. +VA Native | The main purpose of this layer is to accomplish 2 tasks: IO redirection and the request modification for VA APP to interact with Android system.
1. IO redirection is some APPs may be accessed through the hard code absolute path. But if the APP is not installed to the system, this path does not exist. Through IO redirection, it will be redirected to the path to install inside VA.
2. In addition, there are some jni functions that cannot be hooked in VA Framework, so they need to be hooked in the native layer. +
+ +In summary: +As you can see from the above technical architecture, the internal VA APP actually runs on top of VA's own VA Framework. VA has intercepted all system requests from its internal APP, and through this technology it can also have full control over the APP, not just the multi space. And for the convenience of developers, VA also provides SDK and Hook SDK. + + +## VA Process architecture# +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/va_process.jpg) +There are five types of processes in the VA’s runtime: CHILD process, VA Host Main process, VA Host Plugin process, VAPP Client process, and VAServer process. +To support both 32-bit and 64-bit APPs, VA needs to install two packages: a master package and a plug-in package ( In this document, the main package is 32 bits and the plug-in package is 64 bit ). +Two packages are also necessary because a package can only run in one mode, either 32-bit or 64-bit. So for 32-bit APPs, VA uses the 32-bit main package to run, and for 64-bit APPs, VA uses the 64-bit plug-in package to run. +The main package contains all the code of VA, and the plug-in package contains only one piece of code that loads the main package code for execution, no other code. So plug-in package rarely needs to be updated, just the main package. +In addition, whether the main package is chosen to use 32-bit or 64-bit can be modified in the configuration file ( For example, for users who want to access GooglePlay, it will be modified to 64-bit for the main package and 32-bit for the plug-in package ). + +**The functions and explanations of the each type of process are as follows:**
+ +Process Type | Function +---- | --- +CHILD | Other processes integrated by VA Host, such as: keepalive process, push process, etc. +VA Host Main | The process where the UI main interface of the VA main package is located. The default main package is 32-bit and the plug-in package is 64-bit, which can be modified and switched in the configuration file +VA Host Plugin | The process that supports the plug-in package of 64-bit APP. The default main package is 32-bit and the plug-in package is 64-bit, which can be modified and switched in the configuration file. +VAPP Client | The process generated by the APP installed into VA after it starts, it will modify io.busniess.va:pxxx process name to the real process name of VAPP when it runs. +VAServer | The process where the VA Server is located, it is used to handle requests in VA that are not assigned to the system for processing, such as APP installation processing. +
+ +## VA can satisfy almost all your needs ## +Through the above technical architecture, we can know that VA can fully control APP and provide Hook SDK, which can satisfy almost all your needs in various fields: + +1. Satisfy the need of **dual/multi space** +VA allows you to install multiple WeChat/QQ/WhatsAPP/Facebook and other APPs on the same mobile phone, so you can have one phone with multiple accounts logged in at the same time. + +2. Satisfy the need of **mobile security** +VA provides a set of internal and external isolation mechanisms, including but not limited to (file isolation / component isolation / process communication isolation). Simply speaking, VA internal is a "completely independent space". +Through VA, work affairs and personal affairs can be safely separated without mutual interference. With a little customization, you can achieve mobile security-related needs such as application behavior audit, data encryption, data acquisition, data leakage prevention, anti-attack leaks and so on. + **2.1 Application behavior audit** +The HOOK capability provided by VA can realize real-time monitoring of user usage behavior and upload violation information to the server. And it's easy to implement things like Time Fence ( whether a feature of the APP can be used in a certain time ), Geo Fence ( whether a feature of the APP can be used in a certain area ), sensitive keyword filtering interception and other functional requirements. + **2.2 Data encryption** +The HOOK capability provided by VA can realize all data/file encryption of the application, ensuring data/file landing security. + **2.3 Data acquisition** +The HOOK capability provided by VA can realize the demand for real-time silent upload of application data, such as chat records and transfer records, preventing them from being deleted afterwards without traceability. + **2.4 Data leakage prevention** +The HOOK capability provided by VA can realize application anti-copy/paste, anti-screenshot/recording, anti-sharing/forwarding, watermark traceability and other requirements. + **2.5 Anti-attack leaks** +With the application control capability provided by VA, privacy-related behaviors such as SMS/ address book/call log/ background recording/background photo/ browsing history and location information can be completely controlled in sandbox, prevent Trojan horses/malicious APPs from acquiring users' real private data, causing serious consequences such as leakage of secrets. +3. Satisfy the need of **ROOT without HOOK** +VA provides Hook capability of Java and Native. With VA, you can easily achieve functions required by various scenarios, such as virtual positioning, changing device, APP monitoring and management, mobile security and so on. + +4. Satisfy the need of **silent installation** +VA provides the ability to silently install, silently upgrade and silently uninstall APPs. For example, the application store or game center can be integrated with VA to avoid the need for users to manually click to confirm the installation operation, so that it can be installed into VA immediately after downloading, bringing users an experience like "small program" , completely avoiding the problem of applications not easily installed by users. + +5. Satisfy the need of **APP controlled** +You can clearly grasp the system API, sensitive data, device information, etc. accessed by the APP through VA. For example, whether the APP accesses the contacts, photo albums, call log, whether it accesses the user's geographic location and other information. +Of course, you can also control or construct custom messages to these APPs via VA, and not only that, you can also get access to the APP's private data, such as chat database and so on. In a word, through the application control capability provided by VA, you can easily control all the behaviors of the APP, even modify the content of the APP and server interaction and so on .
+ + +6. Satisfy the need of **overseas markets** +VA implements support for Google services to support overseas APPs running, such as Twitter, Messenger, WhatsAPP, Instagram, FaceBook, Youtube and so on. + +7. Satisfy the need of **almost everything you can think of** +VA has complete oversight and control over the internal APP, and can meet almost any of your needs! +8. VA is also the only commercially licensed product in this technology area +**Hundreds of** licensed customers are currently paying to use the business version of VirtualAPP code, and the APP integrated with VirtualAPP code is launched more than 200 million times per day. Many Android engineers provide us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, we continue to improve product performance and compatibility. + + +VA Specialized capabilities +--- + +- Cloning ability
+You can clone the APP already installed in the external system and run it internally without mutual interference. Typical application scenario is double space. + +- Without installation ability
+In addition to cloning already installed, VA can install (externally silent ) apk's directly internally and run them directly internally. Typical application scenarios are plug-in, standalone APP marketplace and so on. + +- Double space ability
+VA is not only "double space", but also has a unique multi-user mode that allows users to open the same APP internally for an unlimited number of times. + +- Internal and external isolation ability
+VA is a standard sandbox, or "virtual machine", that provides a set of internal and external isolation mechanisms, including but not limited to (file isolation/component isolation/process communication isolation). Simply put, the inside of a VA is a "completely separate space". Simply put, the inside of a VA is a "completely separate space". Based on it, you can realize a "virtual phone" on your cell phone with a little customization. Of course, you can also use your imagination to customize it for data encryption, data isolation, privacy protection, and enterprise management applications. + +- Full control over internal APPs ability
+VA has complete monitoring and control over the internal APP, which is absolutely impossible to achieve in an external environment without Root. + +
+Details(Drop down to open) + 1. Service request control. First, VA directly provides some service request interception, you can easily customize these service requests when integrating VA, including but far from limited to (APP request to install apk / APP request to open certain files / APP request for location data / APP request for phone information, etc.)

+ 2. System API control. VA virtualizes and implements the entire Android system framework, which is the principle that VA can run apk internally without installation. And you can through modify the virtual framework's implementation to dynamically monitor and analyze the behavior of the app, etc. In addition, you can also mock some system behavior to achieve some needs that are difficult to achieve externally (e.g. game controller).

+ 3. Memory read and write. VA can read and write the memory of internal APP processes without Root.

+ 4. Root without debugging. VA can debug (ptrace) internal APP processes without Root, based on which you can also achieve Root-free process injection.

+ 5. Load arbitrary "plug-in" and "behaviors". The APP process inside VA is derived from the Client side code of the VA framework, so you can insert any "load" and "control" logic into the entry code of the process. These are very simple to implement.

+ 6. Hook. VA has a set of built-in Xposed framework and native hook framework running on all versions of Android (until AndroidQ), based on it, you can easily Hook any Java/Native of any internal APP.

+ 7. File control. VA built in a complete file redirection, which allows easy control of reading and writing of files from internal apps. Based on it, you can realize many functions such as protection and encryption of files can be achieved.

+ 8. Note: The above control capabilities are implemented with code or examples for reference. +
+ + +VA Other features +--- + +- High performance
+Process-level "virtual machine", VA's unique implementation model makes its performance almost the same as that of the native APP, and does not need a long startup of ordinary virtual machines. + +- Full version support
+Support 5.0-12.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. + +- Easy Expansion and Integration
+The integration of VA is similar to the normal Android library, even if your APP has been online, you can conveniently integrate VA and enjoy the capability brought by VA. + +- Support Google services
+Provide support for Google services in order to support overseas APPs. + + +## Comparison between VA and other technical solutions ## +When doing enterprise-level mobile security, it is often necessary to control the APP, and the following is a comparison of possible technical solutions listed: + +Technical solution | Principle introduction | Comment | Running performance | Compatibility stability | Project maintenance cost +---- | --- | --- | --- | --- | --- +Repackage | Repackage the target APP by decompiling it and adding your own control code | 1. Nowadays, almost all APPs have hardened or tamper-proof protection, and repackaging is already a very difficult task
2.The mobile phone system will also detect whether the APP is repackaged, if it is repackaged, it will directly prompt the user that there is a security risk, and even not allow the installation
3.For each APP, even each version to go deep to reverse analysis, time-consuming and difficult to maintain | Excellent | Poor | High +Custom ROM | By customizing the system source code and compiling it to flash to the designated mobile phone | Only for specified internal mobile phones, too limited to be extended | Excellent | Excellent | High +ROOT the mobile phone | By rooting the mobile phone,flashing a framework which is similar to Xposed | 1.Now, root the mobile phone is an unlikely thing
2.In reality, it is difficult for users to root their own mobile phones | Excellent | Poor | High +VA | Lightweight virtual machine with high speed and low device requirements | No risk point mentioned above | Excellent | Excellent. Hundreds of companies testing feedback at the same time | Low. +VA provides API and a professional technical team to ensure the stable operation of the project +
+As you can see from the above comparison, VA is an excellent product and can reduce your development and maintenance costs. + +## Integrating VA Steps ## +Step 1: Call the VA interface```VirtualCore.get().startup()```in your application to start the VA engine. +Step 2: Call VA interface```VirtualCore.get().installPackageAsUser(userId, packageName)```to install the target APP into VA. +Step 3: Call VA interface```VActivityManager.get().launchApp(userId, packageName)```to start the APP. +**With only the above 3 APIs to complete the basic use, VA has shielded the complex technical details and provided the interface API to make your development easy.** + +## VA compatible stability ## +VA has been extensively tested by ** hundreds of **companies, including **high standards of testing and feedback of dozens of listed companies**, covering almost all types of equipment and scenarios at home and abroad, providing full protection for your stable operation! + + +Up to now, the supported system versions: + +System version | Whether to support +---- | --- +5.0 | support +5.1 | support +6.0 | support +7.0 | support +8.0 | support +9.1 | support +10.0 | support +11.0 | support +12.0 | support +
+ + +Supported App Types: + +App Type | Whether to support +---- | --- +32-bit APP | support +64-bit APP | support +
+ +Supported HOOK Types: + +Hook Type | Whether to support +---- | --- +Java Hook | support +Native Hook | support + +Supported CPU Types: + +Hook Type | Whether to support +---- | --- +ARM 32 | support +ARM 64 | support +
+ +## How to give feedback on problems encountered with integrated VA ? ## +After the purchase of the license we will establish a WeChat group, any problems can always feedback to us, and according to the priority in the first time to deal with. + +## VA Development document ## +Please refer to the VA development documentation:[Development document](doc/VADev_eng.md) + + +License Instructions +------ +VirtualApp virtual machine technology belongs to: Jining Luohe Network Technology Co., LTD. It applied for several VirtualApp intellectual property rights from 2015 to 2021 and` is protected by the Intellectual property Law of the People's Republic of China`.When you need to use the code on Github, **please purchase a business license**,and receive the full source code of the latest VirtualApp business version.Hundreds of licensed customers are paying to use the business version of VirtualApp code, and the app integrated with VirtualApp code is launched more than 200 million times a day. Many Android engineers provided us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, VirtualApp Business Edition code has better performance and higher compatibility. `The company of that year will become one of them after obtaining the license, and enjoy the technological achievements after the continuous iteration. And we can interact and collaborate with our licensed customers operationally, technically and commercially.` + +
+Person in charge: Mr. Zhang
+Telephone: +86 130-321-77777
+WeChat:10890
+
+ + +Serious statement +------ +If you use VirtualApp for **internal use, business profit or upload it to the application market**without licensing. We will take evidence and then report you to the police (for copyright infringement) or prosecute you. It will cause your company to undertake criminal liability and legal action, and affect your company's goodwill and investment.`Purchasing a business license can save you a lot of time developing, testing and refining compatibility, leaving you more time for innovation and profitability.`Luo He Technology has called to the police and sued a number of individuals and companies in 2020.
+ +**In response to the national call for the protection of intellectual property rights! Anyone who reports that his or her company or other companies are using VirtualApp code to develop products without licensing will be given a cash reward upon verification. We will keep the identity of the whistleblower confidential! Reporting WeChat: 10890.** + +
+ +Major updates of the business version +------ + +1. Compatible with the latest Android S +2. Not easily misreported by anti-virus software +3. Framework optimization, performance greatly improved +4. Mobile system and APP compatibility greatly improved +5. Run Google services perfectly +6. Supports running pure 64-bit Apps +7. Built-in `XPosed Hook` framework +8. Add positioning mock code +9. Add code to change device +10. Nearly 400 other fixes and improvements, please see the following table for detail + +
+ +2017 - 2021 Business Edition Code Update Details +------ + +**September 21, 2021 to October 27, 2021 Business Edition Code Updates** + +371、Fix the compatibility problem of Tik Tok Speed version
+370、Fix readlinkat return value precision
+369、Fix the problem of installing APP from outside, not referencing org.apache.http.legacy
+368、Fix Huawei Nova 5i, 64-bit main package compatibility
+367、Fix external storage redirection issue on 11.0
+366、Fix the GMS login problem on 11.0
+365、Fix 11.0 some APP read and write sdcard error problem
+364、Fix the problem that APP may not open after the death of VA core process
+363、Add the error log that can't start when no plug-in is installed
+ + +**August 22, 2021 to September 20, 2021 Business Edition Code Updates** + +362、Horizontal screen re-adaptation
+361、Fix the problem that some APPs cannot be opened after installation through file protocol
+360、Fix the problem of Intent data loss in the Intent passed to JobIntentService
+359、Fix the problem that the second call of JobIntentService does not work
+358、Fix the problem of crashing some APPs on Huawei cell phones
+357、Fix the game login problem on Xiaomi phone
+356、Fix the problem that some applications cannot be opened after reinforcement
+355、Add detection of associated start permission
+354、targetSdk 30 adaptation
+353、Fix the problem that some applications can't access the Internet when targetSdk is 30
+352、Fix the problem that sdcard can't be accessed when targetSdk is 30
+351、Use cmake to replace gradle task in compile script.
+350、Remove obsolete documents
+ +
+December 2017 to August 21, 2021 Business Edition code updates (Drop down to open) + +**August 7, 2021 to August 21, 2021 Business Edition code Updates** + +349、Tweak and optimize gradle script
+348、hidedenApiBypass support for Android R+
+347、targetSdk 30 support
+346、Fixthe bug that VIVO system service
+345、Fix the bug that VIVO phone can't use camera
+344、Fix dex loading abnormal state acquisition
+343、Fix libart.so path problem on Android R
+342、Fix the bug of Andoid Q+ delete notification
+341、Fix the permission check of APN uri
+340、Fix Android R suspend resume thread state
+339、Fix some hook failure cases in debug mode
+338、Fix some bugs of hook after R
+ +**April 25, 2021 to August 6, 2021 Business Edition Code Updates** + +337、Fix the problem that some phones cannot upload avatars in Tan Tan
+336、Fix Android 10 Huawei device IO redirection problem
+335、Adjust the horizontal and vertical screen logic, reduce the occurrence of abnormalities
+334、Add the callback interface of Activity life cycle
+333、Fix the broadcasting problem of Android 12
+332、Fix the bug of abnormal status of some interfaces of WeChat
+331、Fix the support of Outlook, One drive, Teams, Zoom and other overseas APPs.
+330、Fix the bug Android 11 a permission request
+329、Fix the problem that some cocos2d engines only display half screen
+328、Fix the problem that WeChat can not send files under multi-user
+327、split apk support
+326、Android S support
+ +**February 24, 2021 to April 24, 2021 Business Edition Code Updates** + +325、Adapt to multi-user environment
+324、Fix the compatibility problem of the new version of WeChat
+323、Compatible with more enterprise level reinforcement
+322、Support VAPP setting power source optimization
+321、Fix missing permission statement
+320、Fix the reference of android.test.base library on Android 11
+319、Optimize ext plugin judgment
+318、Optimize the selection of ABI during installation
+317、Fix Google docs crash on Android 11
+ +**October 15, 2020 to February 23, 2021 Business Edition Code Updates** + +316、Solve the compatibility of the new version of Love Encryption, Bang Bang and other reinforcement
+315、Fix the problem of WhatsApp not showing cold boot Splash
+314、Optimize the recognition of system APP
+313、Improve the support in multi-user environment
+312、Solve the problem that ext plug-in is stuck in some cases
+311、Support Google Play to download APP in VirtualAPP
+310、Fix the problem that Android 11 QQ can not display pictures
+309、Compatible with Android 11 running Google Service
+308、Fix the problem that Android 11 can't run chromium
+307、Support Hook @CriticalNative Method
+306、Fix the problem that JDK 13 cannot be compiled and run
+305、Fix the problem that Service may crash in some cases
+304、Fix the problem that Android 11 cannot load private data of external storage
+303、Fix the problem that low version APP cannot use org.apache.http.legacy
+302、Fix the problem that the system task stack only shows the last one in some cases
+301、Improve the build script for different platforms
+300、Fix the problem that Android 11 cannot read obb
+299、Fix the problem that the software is not backward compatible
+298、Rebuild VAPP installation framework
+297、Rebuild virtual file system
+296、Fix the problem that WebView cannot be started under certain circumstances
+295、Fix the bug of VAPP uninstall and reinstall
+294、Fix the mobile game "LOL" login exception problem
+293、Support the installation of Splits APK
+292、Support dynamic configuration of the main package environment
+291、Fix the problem of 32-bit QQ calling 64-bit WeChat delay
+290、Fix the problem of Messenger calling Facebook crash
+289、Optimize the support of Google service framework
+288、Realize the new extension package synchronization mechanism
+287、Fix the exception problem of Android 11 official version
+286、Add system Package cache to optimize performance
+285、Fix the bug that the disabled component can still be queried by PMS
+284、Fix the problem of abnormal Launch behavior in some interfaces of WeChat
+283、Fix the bug that ContentProvider.getCallingPackage returns Host package name
+282、Fix the bug of uid virtualization and solve the problem that some app permission check fails
+281、Rewrite the implementation of PendingIntent, IntentSender
+280、Optimize process management, fix the long-standing probabilistic process deadlock problem
+279、Rewrite Service implementation, Service life cycle more accurate, not easy to be killed
+ + +**September 13, 2020 to October 15, 2020 Business Edition Code Updates** + +278、Fix the problem that 64-bit APP cannot call 32-bit APP
+277、Fix the problem of loading HttpClient in Android R
+276、Fix the problem of a crash in Android R debug mode
+ +**August 23, 2020 to September 12, 2020 Business Edition Code Updates** + +275、Add the missing service hook
+274、Fix the problem that Baidu Translate cannot be started
+273、Fix the problem that the split app downloaded by GP cannot be started
+ +**July 10, 2020 to August 22, 2020 Business Edition Code Updates** + +272、Fix Service creation
+271、Add missing Hook for NotificationService
+270、Fix Yotube crash
+ +**May 19, 2020 to July 9, 2020 Business Edition Code Updates** + +269、Preliminary adaptation of Android 11 beta1
+268、Fix the problem of multi space flashback in RED
+267、Fix the problem of "Application signature is tampered" reported by multi space of some APPs
+ +**April 24, 2020 to May 18, 2020 Business Edition Code Updates** + +266、Fix sh call error
+265、Fix the problem that Facebook cannot be logged in in the latest version of 9.0 or above
+264、Help Enterprise WeChat to fix the problem that it can't take photos when starting virtual storage
+263、Fix the problem that 64-bit APP can't open Activity in some cases
+ +**March 24, 2020 to April 23, 2020 Business Edition Code Updates** + +262、Fix the problem that Vivo device prompts to install game SDK
+261、Fix the problem that Android Q cannot load some system so
+260、Fix Huawei device microblog not responding
+259、Ignore crashes caused by unnecessary permission checks
+258、Fix the crash of WPS sharing files
+257、Flashback issue in some 10.0 devices
+ +**March 7, 2020 to March 23, 2020 Business Edition Code Updates** + +256、Fix WeChat open two pages at the same time problem
+255、Fix the problem that WeChat login successfully but return to the login page
+254、Fix the problem that the latest version of QQ can not download attachments
+253、Update SandHook version
+252、Fix the problem of unsigned Apk installed above 9.0
+251、Fix the positioning problem of 10.0
+ +**January 16, 2020 to March 6, 2020 Business Edition Code Updates** + +250、Tweak lib redirection logic
+249、Fix crash issue on Samsung 10.0 systems
+248、Fix hook exception in release build
+247、Add SandHook proguard rules
+246、Fix compatibility issue with VirtualApk in some APPs
+245、Fixed VA internal request to install apk failed
+ +**December 26, 2019 to January 15, 2020 Business Edition Code Updates** + +244、Fix a missing hook in Android Q
+243、Disable AutoFill in Emui10
+242、Add new api to end all Activity
+ +**December 15, 2019 to December 25, 2019 Business Edition Code Updates** + +241、Fix the problem that enterprise WeChat and other apps cannot be launched on Emui10
+240、Fix a possible crash in 4.x
+239、Upgrade SandHook to fix Hook for Thread class
+238、Fix the permission problem caused by some interfaces of Android Q
+ +**November 20, 2019 to December 14, 2019 Business Edition Code Updates** + +237、Fix crash caused by Notification cache
+236、Fix classloader issue of high version Notification
+ +**November 9, 2019 to November 19, 2019 Business Edition Code Updates** + +235、Fix ART Hook for Android 5.x
+234、Fix the deadlock problem caused by ART Hook
+ +**November 2, 2019 to November 8, 2019 Business Edition Code Updates** + +233、Fix WPS, NetEase Mail, etc. crashing on Q devices
+232、Fix the problem that Tom Cat Run crashes on some Q devices
+231、Fix the problem that QQ crashes on some Q devices
+ +**October 25, 2019 to November 1, 2019 Business Edition Code Updates** + +230、Fix cloning Google Play download of 64-bit APP
+229、Fix Enterprise WeChat
+228、Fix Telegram
+ +**October 8, 2019 to October 24, 2019 Business Edition Code Updates** + +227、Fix the exception of AppOspManager under Android P
+226、Add the missing Hook of ActivityTaskManager under Android P
+225、Fix the exception of Activity Top Resume under Android P
+224、Support running in system multi-user mode
+ +**October 8, 2019 Business Edition Code Updates** + +223、Fix the issue of Android P or above internal app returning to desktop exception
+222、64-bit branch support for Android Q
+ +**September 20, 2019 to October 7, 2019 Business Edition Code Updates** + +221、Fix the problem that the apk installed in the extension plugin cannot display the icon and name correctly
+220、Fix the problem that twitter cannot be opened
+219、Officially compatible with Android Q official version
+218、Fix the problem that some Activity of Android Q cannot be opened again
+217、Initially compatible with Android Q official version
+216、Fix several bugs of 64-bit branch
+215、Newly add 64-bit branch to support 32-bit plugins, the branch supports 32-bit old devices and 64-bit devices can support 32-bit old applications in the case of 32-bit plug-ins
+ +**December 2017 to July 30, 2019 Business Edition Code Updates** + +214、Improve APP layer prompt message
+213、Improve some code
+212、Fix the method of sending broadcast from host to plug-in
+211、Compatible with the latest gradle plug-in
+210、Add broadcast namespace to avoid multiple APPs that use VA technology to interfere with each other
+209、Fix the problem that IMO can't be opened
+208、Fix the problem that some ContentProvider cannot be found
+207、Support pure 32-bit mode to be compatible with old devices
+206、Preliminary support for pure 64-bit mode to cope with the change of Google Marketplace strategy in August
+205、Adapt to Android Q beta4
+204、Fix the problem that Cargo LaLa can't be installed
+203、Optimize the decision logic of 64-bit apk
+202、Fix networking of App with network certificate configuration
+201、Refactored component state management
+200、Optimize MIUI/EMUI ContentProvider compatibility
+199、Fix StorageStats Hook
+198、Fix Kwai can't login
+197、Fix YY can not start, better compatibility with plug-in framework
+196、Fix Facebook login
+195、Fix the problem of Google Play downloaded App can not find so (Royal War)
+194、Fix split apk support
+193、Fix Youtube can not start
+192、Fix the problem that Youku can not start
+191、Fix the bug that there may be broadcast namespace conflict between apps when multi space
+190、Adopt a new strategy to bypass the Hidden Policy API after Android P
+189、Adapted to Android Q(beta1)
+188、Fix the problem that some APPs of Huawei devices cannot recognize the storage
+187、Fix the problem that the startup process may fail dues to the APP cannot run
+186、Fix the problem that some native symbols cannot be found in 4.4 devices
+185、Fix the problem that some devices fail to get the package name of WebView
+184、Fix the problem of Service detail processing
+183、Optimize startup speed
+182、Fix WebView loading failure in a few devices
+181、Fix the problem of Lib decision
+180、 Fix the problem that some Huawei models cannot read the sdcard
+179、Fix the problem that Service may exist
+178、Allow to determine whether Activity is started externally based on intent
+177、Fix Gms and Google Play launching to incorrect environment on some models
+176、Fix the compatibility problem caused by the newly implemented StaticBroadcast
+175、Fix the problem that apache.http.legacy cannot be used on Android P
+174、Implementation of Native trace
+173、Optimize IO Redirect performance
+172、Fix the problem that wechat can't connect to the network in some cases
+171、Fix the small probability process attach of incorrect BUG
+170、Start the next phase of ROADMAP
+169、Fix the problem caused by the inability of Android P to register more than 1000 broadcasts
+168、Fix the DeadLock that may cause ANR
+167、Fix the problem that some apps fail to load so dynamically
+166、Fix the problem that some models have black screen when opened for the first time under the without installation running environment
+165、Compatible with many mainstream Android emulators
+164、Optimize startup performance
+163、Solve several memory leaks
+162、Fix the problem of IO Redirect priority
+161、Fix the problem of no network connection of Messenger for devices below 8.0
+160、Fix the bug that the internal app is still retained when the external APP is uninstalled when double space
+159、Fix the problem that some Tencent reinforcement cannot run
+158、 Fix the bug that Instagram cannot login to Facebook
+157、Fix the bug that the process may start repeatedly with small probability
+156、Fix the bug that GET_PERMISSIONS does not get permission
+155、Fix the bug that startActivityIntentSender
+154、Fix the problem that some Activity cannot be started in Vivo devices
+153、Fix the problem that app cannot call external APP to select files
+152、Improve the compatibility of Android P
+151、Compatible with Google service of Android P
+150、Fix the problem that some functions of Messenger are abnormal
+149、Improve IO Redirect
+148、Adapt a lot of Gms, fix the problem that the process restarts infinitely during the operation of Gms
+147、Realize the running mechanism of Service
+146、Improve 64bit, provide some ROM configuration 64bit Engine permission API
+145、Fix the Activity startup problem on 4.4 devices
+144、Support excludeFromRecent property
+143、Fix the problem that Instagram can't Facebook login
+142、Fix the problem of Facebook first login flashback
+141、Support to run Gms, Google play, Play game in 64-bit mode
+140、Support downloading and installing APPs in Google play running without installation/in multi space
+139、Fix the bug of DownloadManagerG
+138、Fix the bug of restarting the interface when Google play returns to the upper level
+137、Fix the problem of so decision in without installation mode
+136、Optimize the build script to facilitate the introduction of the project
+135、Fix the problem that mobile MM SDK can't start
+134、Fix the bug of WeChat Shake
+133、Fix the bug of ZTE device instability
+132、Support IO Redirect under ARM64
+131、Fix the bug that the internal app is not updated when the external app is updated in USE_OUTSIDE mode
+130、Compatible with the latest Android 9.0 (code name: pie) and the four Preview versions released before the official version
+129、Compatible with x86 devices with built-in houdini
+128、WindowPreview technology, so that the app launch and the real app to achieve the same speed
+127、New ActivityStack to improve the quality of APP running
+126、Solve the problem of app running exception with adding Atlas Framework
+125、Now you can define the specific behavior of the virtual app back to the desktop
+124、APP in the double space dynamically updated with the system, no need to manually check
+123、Support targetSdkVersion >= 26, but still can normally run the low version of the APP
+122、Compatible with QDroid virtual engine of Tencent Game Manager (beta)
+121、Extensive refactoring of the underlying code to greatly improve the running speed
+120、Fix the problem that NetEase News cannot be cancelled after sharing to Weibo
+119、Fix the problem that APP custom permission cannot be identified
+118、Fix the problem that the MoJi weatherAPP can not start
+117、Fix the problem that some government APPs cannot be started
+116、See code for details of API changes
+115、Fix the problem of Samsung series APPs calling each other
+114、Fix the account problem of Xiaomi APP in non-Xiaomi system
+113、Fix third-party calls such as share/send, the return page is not normal
+112、Fix the problem of APP Store of QQ can not be installed
+111、Call the third-party APP, encryption of uri
+110、Adapt the front bangs
+109、Adapt the hook of Xiaomi rom
+108、Adapt Nubia recording problem
+107、 Internal hover window permission control
+106、Optimize the processing of custom notification bar
+105、Fix the INCLUDE_CODE permission problem of Context
+104、Adapt Huawei, oppo's corner mark
+103、Fix the process restart problem of Baidu video
+102、Fix some snapchat can not start problem
+101、Adapt autofill service, such as piexl series
+100、Improve the 64-bit io hook
+99、Optimize the compatibility of hook library, add back dlopen
+98、Move the 64-bit extension package so to the 32-bit main package. (After jni code change, please build once before Run)
+97、Notification bar changes: adapt 8.1 notification channel; remove the application, remove all notifications of the application
+96、Compatible with some APPs, need to set android:largeHeap=true
+95、Fix the ffmpeg library video can not play the problem
+94、Optimize horizontal and vertical screen switching
+93、Lower the limitation of calling external Activity through Intent
+92、Compatible with MG SDK
+91、64-bit support is still in the development stage
+90、Update obfuscation configuration APP/proguard-rules.pro, must add the rule -dontshrink
+89、Optimize the mock device, for example: after mock, some APPs do not appear device verification
+88、Improve dex2oat compatibility
+87、Optimize mock positioning
+86、Remove dlopen
+85、targetVersion can be changed to 26: support targetVersion<23 app dynamic permission application, support targetVersion<24 file Uri
+84、installPackage changed to default asynchronous form
+83、In order to support 64-bit mode, change back to aidl
+82、Remove SettingHandler can now dynamically set special rules, the rules will be stored, no need to repeat settings
+81、Add 2 native_setup
+80、Improve jobService compatibility
+79、ShortcutService related: associated VASettings.ENABLE_INNER_SHORTCUT
+78、For the sake of stability and running efficiency, remove the Bluetooth, wifi and undeclared permission adaptations of the previous version
+77、Add APP starts abnormal broadcast Constants.ACTION_PROCESS_ERROR
+76、Fix a few games horizontal screen judgment problem
+75、Demo adds device mock
+74、Adapt Vivo a custom permission (background pop-up), VA is to return a history acitivty to the foreground. Vivo needs this permission
+73、If there is no Bluetooth permission, return to the default value (overseas use it)
+72、Fix uid permission check problem
+71、Security updates, file permission control for internal applications
+70、Improve the compatibility of internal APP calls, third-party login, sharing
+69、Automatic filtering of external ContentProvider without permissions
+68、Add feature: internal APP permission check (closed by default)
+67、Device mock: Build class and build.prop
+66、Improve the compatibility of the APP progard
+65、Adapt to Samsung wifimanager
+64、Fix ipc framework a parameter passing problem (IPCMethod this class must be updated)
+63、Fill the 7.0 notification bar hook
+62、Fix 8.0 dynamic shortcut menu hook
+61、SettingHandler adds a new adaptation interface, mainly adapted to a variety of games
+60、Functional changes: google automatic installation to manual installation, to avoid the first start time too long
+59、Prohibit access to an external ContentProvider
+58、Adapt Huawei desktop icon number
+57、Permission classification notes, mark the permissions that can be deleted
+56、Add a switch for the APP in double space mode to follow external upgrade
+55、Improve the APP jni compatibility
+54、Improve compatibility with APP integration of other plug-in frameworks
+53、Add setting interface to set according to package name
+52、Increase the scope of Uri adaptation to support sharing and viewing files via Uri
+51、Fix a problem in Samsung 8.0
+50、Improve the compatibility of the app components that come with the system, better compatibility with chrome webview, google service.
+49、Improve the stability of ART
+48、Increase camera adaptation range
+47、Support internal App shortcut management under 8.0
+46、Fix exec exception
+45、Improve stability (Fix WeChat login flashback)
+44、Fix the WeChat database crash problem
+43、Fix the crash problem of some 4.4 devices
+42、Fix the background application easy to be killed, Tudou video black screen, Sina Weibo can not open, Youku twice return can not exit
+41、Increase the application keepalive mechanism, APP double space is less likely to be killed
+40、Optimize the performance of virtual engine startup
+39、Compatible with most of the reinforcement, third-party APP compatibility compared to the previous version to improve 40% +
+38、Fix the shortcut icon is incorrect under some roms
+37、Compatible with previous component StubFileProvider
+36、Adapt the virtual IMEI of some new roms
+35、Improve process initialization code to increase stability
+34、Add internal send Intent.ACTION_BOOT_COMPLETED broadcast, you can set the switch
+33、Adapt the associated google play game, support the game using google login
+32、Adapt the google service framework for android O
+31、Adapt android O shortcut
+30、Adapt to headset mode
+29、Some roms on the size of the intent limit, demo add scaling shortcut icon code
+28、Fix the bug in the case of multi space
+27、Fix the bug of MediaController in some cases
+26、Fix the error of StubFileProvider in 4.1.2
+25、Share uri processing
+24、Fix the callbacks of cross-app calls to Activity
+23、Block switch of notification bar of foreground service
+22、Companying doc
+21、Improve the CHOOSE callback of intent inside VA
+20、Android O notification bar adaptation 2
+19、 ipc framework optimization, improve the accuracy of determining the survival of the binder
+18、jni's log switch Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE
+17、Confusion configuration
+16、Notification bar adaptation of Android O
+15、Fix the problem of network lag in some APPs
+14、Adaptation of android 8.0 dl_open (jni loading)
+13、Fix the bug of Huawei emui8.0
+12、Improve positioning
+11、Set the phone information, imei disguise algorithm
+10、Adapted to 8.0 a certain function (the main APP: whatsAPP)
+9、Fix internal WeChat and other applications, can not update the picture, video
+8、Demo add the installation of listening, automatically upgrade the clone mode applications
+7、Adaptations of 7.0 file provider adaptations
+6、Add positioning code
+5、The code is optimized for the architecture
+4、Different features from the open source version
+3、Solve some problems of WeChat being blocked
+2、Repaire some devices compatibility
+1、Repaire 12 small bugs
+
+ + + + + diff --git a/doc/VADev.md b/doc/VADev.md index 4fc72ded4..35b920d42 100644 --- a/doc/VADev.md +++ b/doc/VADev.md @@ -4,7 +4,7 @@ 第一部分是VA的源码结构介绍,这部分是为了让开发者能快速了解掌握VA源码框架。 第二部分是VA的基础SDK使用说明。 其他更多的开发文档见:[VA私有库Wiki](https://github.com/asLody/VirtualApp-Priv/wiki) -VA产品说明:[文档](https://github.com/asLody/VirtualApp/blob/master/README.md) +VA产品说明:[文档](../README.md)
**下面开始第一部分,VA源码结构介绍:** diff --git a/doc/VADev_eng.md b/doc/VADev_eng.md new file mode 100644 index 000000000..c74efb718 --- /dev/null +++ b/doc/VADev_eng.md @@ -0,0 +1,534 @@ +

VA Basic Development Document

+ +This document mainly introduces 2 parts. +The first part is the introduction of VA source code structure, this part is to allow developers to quickly understand to master the VA source code framework. +The second part is a description of VA's basic SDK. For more development documents, see: VA Private Library Wiki. +For more development documents, see:[VA Private Library Wiki](https://github.com/asLody/VirtualApp-Priv/wiki) +VA Product Description:[Document](../README_eng.md) +
+ +**The following is the first part, the introduction of the VA source code structure:** + +## 1. Introduction of VA source code directory ## +The following figure is the root of the VA source code: +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/1.png) +You can see that VA has a total of four source code directories, and each directory is described as follows: + +Directory Name | Function +---- | --- +app | The directory where the VA Demo master package source code is located +app-ext | The directory where the source code of VA Demo plug-in package is located +lib | The directory where the VA library source code is located +lib-ext | The directory where the source code of VA Plugin Library is located +
+ +## 2. Introduction of VA compilation configuration profile ## +VA compilation configuration profile isVAConfig.gradle: +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/2_1.jpg) + +Configuration explanation: + +Configuration Name | Function +---- | --- +PACKAGE_NAME | Used to configure the package name of the VA main package +EXT_PACKAGE_NAME | Used to configure the package name of the VA plug-in package +VA_MAIN_PACKAGE_32BIT | Used to configure whether the VA main package is 32-bit or 64-bit, true is 32-bit, false is 64-bit +VA_ACCESS_PERMISSION_NAME | Used to configure the permission names of the 4 major components in VA +VA_AUTHORITY_PREFIX | Used to configure the authorities of ContentProvider in the VA main packag +VA_EXT_AUTHORITY_PREFIX | Used to configure the authorities of the ContentProvider in the VA plug-in package +VA_VERSION | Used to configure the VA library version, developers generally do not need to care +VA_VERSION_CODE | Used to configure the VA library version code, developers generally do not need to care +
+ +## 3. VA core code explanation ## +1. The code under the`com.lody.virtual.client`package runs in the VAPP Client process and is mainly used in the APP Hook part of the VA Framework to complete the HOOK processing for each service. +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_1.png) +2. The code under the`com.lody.virtual.server`package runs in the VA Server process. The code is mainly used in the APP Server part of the VA Framework to handle APP installation and other APP requests that are not handled by the Android system. +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_2.png) +3.The code under the `mirror`package is mainly used for references to the system's hidden classes, and belongs to the tool class, reducing a lot of reflection code's writing. +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_3.png) +4.The code under the `cpp`package is carried out in the VAPP Client process and is mainly used in the VA Native part. Implement IO redirection and jni function HOOK. Among them: + - `substrate`implements hook for arm32 and arm64 + - `vfs.cpp`implements VA's virtual file system for controlling APP file access restrictions + - `syscall_hook.cpp`implements Hook for IO +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_4.png) +5.`DelegateApplicationExt.java`runs in the VA Host Plugin process,used in the VA plug-in package, implementing the loading and execution to the main package code. +![](https://cdn.jsdelivr.net/gh/xxxyanchenxxx/temp@1.0/doc/3_5.png) + +

+**The following is the second part, the introduction of using VA SDK:** + +## 1. VA Project Integration ## +### Open VirtualApp-Priv project with Android Studio + +Multiple modules can be seen: +* app +* app-ext +* lib +* lib-ext + +Among them, **lib** and **lib-ext** belong to the VirtualApp`core library `and `extensions`,while **app** and **app-ext** belong to the`sample app`. + + + +### Create your own App +Create a module of type application, and add the lib module as a dependency +```gradle +implementation project(':lib') +``` + +### Modify VAConfig.gradle according to demand: +```gradle +ext { + VA_MAIN_PACKAGE_32BIT = true // The main package is 32-bit + VA_ACCESS_PERMISSION_NAME = "io.busniess.va.permission.SAFE_ACCESS" // The name of the permission used by the VirtualApp component + VA_AUTHORITY_PREFIX = "io.busniess.va" // The authority used by ContentProvider in VirtualApp cannot be duplicated with other Apps. + VA_EXT_AUTHORITY_PREFIX = "io.busniess.va.ext" // The authority used by the ContentProvider in the VirtualApp extension package cannot be duplicated with other Apps. + // ... +} +``` + +### Add the required permissions in AndroidManifest.xml +```xml + +``` +Permission's name must be consistent with those declared in **VAConfig.gradle**, and adding **Placeholder** in **build.gradle** to prevent errors. +``` gradle +android { + // ... + manifestPlaceholders = [ + VA_ACCESS_PERMISSION_NAME: rootProject.ext.VA_ACCESS_PERMISSION_NAME, + ] +} +``` + +### Create an Application + +#### Override the attachBaseContext method and add the code to bootstrap the VirtualApp: + +```java + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(base); + try { + VirtualCore.get().startup(base, mConfig); + } catch (Throwable e) { + e.printStackTrace(); + } + } + +``` + +#### Here, a configuration of VirtualApp is passed in mConfig +```java +private SettingConfig mConfig = new SettingConfig() { + @Override + public String getMainPackageName() { + // Name of the main package + return BuildConfig.APPLICATION_ID; + } + + @Override + public String getExtPackageName() { + // Name of extension package + return BuildConfig.EXT_PACKAGE_NAME; + } + + @Override + public boolean isEnableIORedirect() { + // Whether to enable IO redirection, it is recommended to enable + return true; + } + + @Override + public Intent onHandleLauncherIntent(Intent originIntent) { + // Back to the desktop of the Intent interception operation. Here change the action that back to the desktop to return to BackHomeActivity page of the main package. + Intent intent = new Intent(); + ComponentName component = new ComponentName(getMainPackageName(), BackHomeActivity.class.getName()); + intent.setComponent(component); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return intent; + } + + @Override + public boolean isUseRealDataDir(String packageName) { + // The data path simulates the real path format and requires IO redirection to be enabled. Some of the hardening will check the path format. + return false; + } + + @Override + public boolean isOutsidePackage(String packageName) { + // Whether is an external App. Set the external App to be visible to the internal App. + return false; + } + + @Override + public boolean isAllowCreateShortcut() { + // Whether allow to create desktop shortcut icons. It is recommended to turn off (false) and implement desktop shortcuts by yourself. + return false; + } + + @Override + public boolean isHostIntent(Intent intent) { + // Whether the Intent is handled by VirtualApp. + return intent.getData() != null && "market".equals(intent.getData().getScheme()); + } + + @Override + public boolean isUseRealApkPath(String packageName) { + // The installation apk path simulates the real path and requires IO redirection to be enabled. Some hardening will check the path format. + return false; + } + + @Override + public boolean isEnableVirtualSdcardAndroidData() { + // Enable redirection of `Android/data` directory under external storage. + // Require redirection support. + // Must be enabled after Android 11!! + return BuildCompat.isR(); + } + + @Override + public String getVirtualSdcardAndroidDataName() { + // Set the redirect path for `Android/data` directory under external storage. + // /sdcard/Android/data/com.example.test/ ==>> /sdcard/{VirtualSdcardAndroidDataName}/{user_id}/Android/data/com.example.test/ + return "Android_va"; + } + + @Override + public FakeWifiStatus getFakeWifiStatus() { + // Modify the wifi information. null is not modified. + return null; + } + + @Override + public boolean isHideForegroundNotification() { + // Hide foreground messages, not recommended to hide. + return false; + } + + @Override + public boolean isOutsideAction(String action) { + // Action event response of external Intent. + return MediaStore.ACTION_IMAGE_CAPTURE.equals(action) + || MediaStore.ACTION_VIDEO_CAPTURE.equals(action) + || Intent.ACTION_PICK.equals(action); + } + + @Override + public boolean isDisableDrawOverlays(String packageName) { + // Disable top-level overlay (floating window) for VAPP. + return false; + } + }; +``` + +### Override onCreate and add the code of initialize the VirtualApp: +```java + @Override + public void onCreate() { + super.onCreate(); + VirtualCore virtualCore = VirtualCore.get(); + virtualCore.initialize(new VirtualCore.VirtualInitializer() { + @Override + public void onMainProcess() { + // Main process callback + } + + @Override + public void onVirtualProcess() { + // Virtual App process callback + } + + @Override + public void onServerProcess() { + // Server-side process callback + } + + @Override + public void onChildProcess() { + // Other sub-process callback + } + }); + } + +``` + +Since VirtualApp will start multiple processes, Application will enter N times, and different processes will go to different callbacks of VirtualInitializer, where additional initialization code can be added depending on the process type. + +## 2. Install the APP ## +## API: +```java +VirtualCore.java + + public VAppInstallerResult installPackage(Uri uri, VAppInstallerParams params); +``` +## What is the parameter Uri? +Uri determines the source of **the apk that need to be installed**,and currently supports both package and file protocols. +### Package Uri Example: +```java +Uri packageUri = Uri.parse("package:com.hello.world"); +``` +### File Uri Example: +```java +File apkFile = new File("/sdcard/test.apk"); +Uri packageUri = Uri.fromFile(apkFile); +``` + +## What is the difference between the two types of Uri installation apps? +**package agreement** To install the app, you only need to pass in the package name, not the specific APK path, so the app installed with this protocol **is equivalent to double space**. + +The APP is automatically upgraded as external versions are upgraded and uninstalled as external versions are uninstalled. `dynamic` in `PackageSetting` is `true`。 + +**file agreement** It is an internal installation, apk is copied inside the container, completely independent from the external version. `dynamic` in `PackageSetting` is `false`。 + +## Installation Parameters VAppInstallerParams + +### Installation Flags installFlags + +FLAG | Instruction +--- | --- +FLAG_INSTALL_OVERRIDE_NO_CHECK | Allow overlay installation +FLAG_INSTALL_OVERRIDE_FORBIDDEN | Prohibit overlay installation +FLAG_INSTALL_OVERRIDE_DONT_KILL_APP | Overwrite installation, and not kill the already launched APP + +### Installation Mode mode + +FLAG | Instruction +--- | --- +MODE_FULL_INSTALL | Complete installation +MODE_INHERIT_EXISTING | The installed installation mode of the installed. Reserve. + +Reserve parameters, not used for now. Currently the same no matter which one is set. + +### cpuAbiOverride + +Specify the abi of the App. You can force the App to run under the specified abi in special need. If you don't specify, the default abi is determined by `system rules`. +Optional parameters: +* armeabi +* armeabi-v7a +* arm64-v8a + +### Double space App example code: +```java +VAppInstallerParams params = new VAppInstallerParams(VAppInstallerParams.FLAG_INSTALL_OVERRIDE_NO_CHECK); +VAppInstallerResult result = VirtualCore.get().installPackage(Uri.parse("package:com.tencent.mobileqq"), params); +if (result.status == VAppInstallerResult.STATUS_SUCCESS) { + Log.e("test", "install apk success."); +} +``` + +### Install apk from sd card example code: +```java +VAppInstallerParams params = new VAppInstallerParams(VAppInstallerParams.FLAG_INSTALL_OVERRIDE_NO_CHECK); +VAppInstallerResult result = VirtualCore.get().installPackage(Uri.fromFile(new File("/sdcard/test.apk")), params); +if (result.status == VAppInstallerResult.STATUS_SUCCESS) { + Log.e("test", "install apk success."); +} +``` + +### Install Split apk +Just install the base package firstly, and then install all the split packages. +```java +File dir = new File("/sdcard/YouTube_XAPK_Unzip/"); +VAppInstallerParams params = new VAppInstallerParams(VAppInstallerParams.FLAG_INSTALL_OVERRIDE_NO_CHECK); +VAppInstallerResult result = VirtualCore.get().installPackage( + Uri.fromFile(new File(dir,"com.google.android.youtube.apk")), params); +for (File file : dir.listFiles()) { + String name = file.getName(); + if (name.startsWith("config.") && name.endsWith(".apk")) { + result = VirtualCore.get().installPackage( + Uri.fromFile(file), params); + } +} + +``` + + + + +## 3. Launch and manage Application ## +# Launch App + +```java +// class VActivityManager +public boolean launchApp(final int userId, String packageName) +```` +Example code: +```java +VActivityManager.get().launchApp(0, "com.tencent.mobileqq"); +``` + +# Kill App +```java +// class VActivityManager +public void killAppByPkg(String pkg, int userId) +public void killAllApps() +``` +Example code: +```java +// Kill the QQ program process with userid 0 +VActivityManager.get().killAppByPkg("com.tencent.mobileqq", 0); + +``` + +```java +// Kill all App processes +VActivityManager.get().killAllApps(); +``` + +# Uninstall App +```java +// class VirtualCore +public boolean uninstallPackageAsUser(String pkgName, int userId) +public boolean uninstallPackage(String pkgName) +``` +Example code: +```java +// Uninstall the QQ program with userid 0 +VirtualCore.get().uninstallPackageAsUser("com.tencent.mobileqq", 0); +// Uninstall the QQ programs installed under all user +VirtualCore.get().uninstallPackage("com.tencent.mobileqq"); +``` + +# Check the installed Apps +```java +// class VirtualCore +public List getInstalledApps(int flags) +``` + +## 4. Java Hook Usage ## +VirtualApp implements a set of Xposed interface. Users who can use Xposed can do things that originally need the system built-in Xposed to do. +However, users also need to understand that the scope of Xposed in VA is within the VA app. Cannot overstep the authority to control system or other external apps. + + +VA provides a callback interface of App creation and launch `com.lody.virtual.client.core.AppCallback`, the interfaces are as follows: +```java +public interface AppCallback { + void beforeStartApplication(String packageName, String processName, Context context); + + void beforeApplicationCreate(String packageName, String processName, Application application); + + void afterApplicationCreate(String packageName, String processName, Application application); +} +``` + +> Interface Instruction: + +Name | Instruction +---- | --- +beforeStartApplication | Before APP launch, after creation +beforeApplicationCreate | Before the APP is created, application has already prepared, Application.OnCreate is not executed. +afterApplicationCreate | After the APP is created, Application.OnCreate is executed. + +
+ +>Parameter Instruction: + +Name | Instruction +---- | --- +packageName | Name of VAPP +processName | Process name of VAPP +context | Application context of VAPP +application | Application of VAPP + +
+ +> Note: APP creation means that`Application`is created. + +The interface is there, and the next step is how to use it. View[`VirualApp Process Instruction`](VirualApp Process Instruction.md), we kan see +We just need to put in the`VAPP process`callback(`onVirtualProcess`) set App callback `AppCallback` and then achieve the purpose. + +> Host Application code, please refer [io/busniess/va/App.java](https://github.com/asLody/VirtualApp-Priv/blob/v2.1/VirtualApp/app/src/main/java/io/busniess/va/App.java) + +```java +@Override + public void onCreate() { + super.onCreate(); + VirtualCore virtualCore = VirtualCore.get(); + virtualCore.initialize(new VirtualCore.VirtualInitializer() { + @Override + public void onVirtualProcess() { + // Set VAPP launch callback + virtualCore.setAppCallback(new MyComponentDelegate()); + } + }); + } +``` + +> [MyComponentDelegate](https://github.com/asLody/VirtualApp-Priv/blob/v2.1/VirtualApp/app/src/main/java/io/busniess/va/delegate/MyComponentDelegate.java)Class Code + +```java +public class MyComponentDelegate implements AppCallback { + + @Override + public void beforeStartApplication(String packageName, String processName, Context context) { + } + + @Override + public void beforeApplicationCreate(String packageName, String processName, Application application) { + + XposedHelpers.findAndHookMethod("android.app.ContextImpl", ClassLoader.getSystemClassLoader(), "getOpPackageName", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + VLog.printStackTrace("getOpPackageName"); + param.setResult(VirtualCore.get().getHostPkg()); + } + }); + } + + @Override + public void afterApplicationCreate(String packageName, String processName, Application application) { + } +} +``` + +In the above example, a use case for Xposed has been added. The entry point of Xposed is an example of `IXposedHookLoadPackage`, it provides an interface of `void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam)`. There is one parameter of `XC_LoadPackage.LoadPackageParam`. Here we can't use it exactly one by one, but it's enough. `loadPackageParam.classsload`can use `context.getClassLoader()` or `application.getClassLoader()` both are ok. Afterwards `XposedHelpers`, the same way how to use`XposedBridge`, is also used here. + + + +## 5. Native Hook Usage ## +For ARM 32 and ARM 64 Hooks, only the header files ```CydiaSubstrate.h``` need to be introduced, i.e. the Hook API: +```MSHookFunction(Type_ *symbol, Type_ *replace, Type_ **result)``` +>Parameter Instruction: + +Name | Instruction +---- | --- +symbol | Address to Hook +replace | Your custom Hook function +result | Backups of hooked function +
+Refer ```syscall_hook.cpp``` code +```cpp +auto is_accessible_str = "__dl__ZN19android_namespace_t13is_accessibleERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE"; +void *is_accessible_addr = getSym(linker_path, is_accessible_str); +if (is_accessible_addr) { + MSHookFunction(is_accessible_addr, (void *) new_is_accessible,(void **) &orig_is_accessible); +} +``` + +Within `MSHookFunction`, it automatically determines whether the current is ARM32 or ARM64: + + +```cpp +_extern void MSHookFunction(void *symbol, void *replace, void **result) { + if (*result != nullptr) { + return; + } + // ALOGE("[MSHookFunction] symbol(%p) replace(%p) result(%p)", symbol, replace, *result); +#ifdef __aarch64__ + A64HookFunction(symbol, replace, result); +#else + SubstrateHookFunction(NULL, symbol, replace, result); +#endif +} +``` + + +
+
+ +[Additional development guidance can be found on the VA Private Library Wiki](https://github.com/asLody/VirtualApp-Priv/wiki) + +
+
From bfa3a29a107527d2104275c2e4050895a12f13d8 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 9 Nov 2021 17:08:51 +0800 Subject: [PATCH 211/334] Update README_eng.md --- README_eng.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_eng.md b/README_eng.md index 1fc579bda..c519e0b35 100644 --- a/README_eng.md +++ b/README_eng.md @@ -4,7 +4,7 @@

VA Product description & Development guidance

## What is VA? ## -VirtualAPP (abbreviation: VA) is a sandbox product running on Android system, which can be understood as a lightweight "Android virtual machine". Its product form is a highly extensible, customizable, integrated SDK that allows you to develop a variety of seemingly impossible projects based on or using VA. Now, VA is widely used in in many technology fields as following: mini game collection, blockchain, cloud control, silent hot fix and so on. On the one hand, you can realize cloud control mobile office security and achieve military and government data isolation with VA. On the other hand, you can implement script automation, device-info-mock, and plug-in development. Meanwhile, you can realize multi space and games booster. You can also rent the mobile game account and use the mobile controller without activation by VA.
**The code on Github has stopped updating in December 2017. The code of business version is continuously being updated. If you need license to obtain the latest code, please contact WeChat: 10890.** +VirtualAPP (abbreviation: VA) is a sandbox product running on Android system, which can be understood as a lightweight "Android virtual machine". Its product form is a highly extensible, customizable, integrated SDK that allows you to develop a variety of seemingly impossible projects based on or using VA. Now, VA is widely used in many technology fields as following: mini game collection, blockchain, cloud control, silent hot fix and so on. On the one hand, you can realize cloud control mobile office security and achieve military and government data isolation with VA. On the other hand, you can implement script automation, device-info-mock, and plug-in development. Meanwhile, you can realize multi space and games booster. You can also rent the mobile game account and use the mobile controller without activation by VA.
**The code on Github has stopped updating in December 2017. The code of business version is continuously being updated. If you need license to obtain the latest code, please contact WeChat: 10890.** ## Terminology in VA ## From 7141f0ab00ce9be17f173cda4eee5eb2369c725d Mon Sep 17 00:00:00 2001 From: YFdyh000 Date: Sun, 14 Nov 2021 16:00:36 +0800 Subject: [PATCH 212/334] fix typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 912869fac..11029de18 100644 --- a/README.md +++ b/README.md @@ -212,7 +212,7 @@ VA开发文档请参考:[开发文档](doc/VADev.md) 授权说明 ------ -VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,于2015年至2021年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当年的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` +VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,于2015年至2021年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
负责人:张总
From ea0b5bd1d9ca7a0ab9c869553c775b8192f71616 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 23 Nov 2021 09:38:49 +0800 Subject: [PATCH 213/334] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 912869fac..612900af8 100644 --- a/README.md +++ b/README.md @@ -248,8 +248,10 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2021年商业版代码更新详细 ------ -**2021年 9月21号 至 2021年 10月27号 商业版代码更新内容** +**2021年 9月21号 至 2021年 11月23号 商业版代码更新内容** +373、修复WhatsApp在360手机上黑屏问题
+372、增加VA内外广播通信测试demo
371、修复抖音极速版兼容性问题
370、修复readlinkat返回值精度
369、修复从外部安装app,没有引用org.apache.http.legacy的问题
From db8b4868dd6cc4793333151e68dc6f1c746abe99 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 23 Dec 2021 16:10:43 +0800 Subject: [PATCH 214/334] Update README.md --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4df025b94..c04883ed1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

VA产品说明&开发指导

## VA是什么? ## -VirtualApp(简称:VA)是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。其产品形态为高可扩展,可定制的集成SDK,您可以基于VA或者使用VA定制开发各种看似不可能完成的项目。VA目前被广泛应用于APP多开、小游戏合集、手游加速器、手游租号、手游手柄免激活、区块链、移动办公安全、军队政府数据隔离、手机模拟信息、脚本自动化、插件化开发、无感知热更新、云控等技术领域。
**Github上代码已在2017年12月份停止更新,商业版代码在持续更新中,如需授权获得最新代码,请联系微信:10890** +VirtualApp(简称:VA)是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。其产品形态为高可扩展,可定制的集成SDK,您可以基于VA或者使用VA定制开发各种看似不可能完成的项目。VA目前被广泛应用于APP多开、小游戏合集、手游加速器、手游租号、手游手柄免激活、VR程序移植、区块链、移动办公安全、军队政府数据隔离、手机模拟信息、脚本自动化、插件化开发、无感知热更新、云控等技术领域。
**Github上代码已在2017年12月份停止更新,商业版代码在持续更新中,如需授权获得最新代码,请联系微信:10890** ## VA中的术语 ## @@ -88,11 +88,15 @@ VA提供了APP静默安装,静默升级,静默卸载的能力。如应用商 6. 可以满足您的**海外市场**需求 VA实现了对Google服务的支持,以支持海外的App运行,比如Twitter、Messenger、WhatsApp、Instagram、FaceBook、Youtube等。 -7. 可以满足您**几乎一切能想到**的需求 + +7. 可以满足您的**VR程序移植**需求 +可以通过VA的Hook能力拦截VR设备的API,让您无需改动代码即可将VR程序移植到新的设备。 + +8. 可以满足您**几乎一切能想到**的需求 VA对于内部的App具有完全的监管和控制能力,几乎能满足您的一切需求! -8. 同时VA也是该技术领域__唯一一款__对外商业授权的产品 -截止目前已有**上百家**授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP__日启动__次数__超过2亿次__,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,不断提升产品性能与兼容性! +9. 同时VA也是该技术领域**唯一一款**对外商业授权的产品 +截止目前已有**上百家**授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP**日启动**次数**超过2亿次**,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,不断提升产品性能与兼容性! VA的特有能力 From e239f9b61579b61405d16cdb3a4cd2bb56a76d06 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 29 Dec 2021 09:22:31 +0800 Subject: [PATCH 215/334] Update README.md --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c04883ed1..2ab7daaad 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,16 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2021年商业版代码更新详细 ------ + +**2021年 11月24号 至 2021年 12月29号 商业版代码更新内容** + +379、Android 12.0第一轮适配已完成
+378、Demo App在11.0上增加文件权限检测
+377、修复静态广播接收者在独立进程无法接收广播的问题
+376、修复微信微信第一次登录可能crash问题
+375、修复部分APP无法显示头像问题
+374、修复部分OPPO手机上打不开问题
+ **2021年 9月21号 至 2021年 11月23号 商业版代码更新内容** 373、修复WhatsApp在360手机上黑屏问题
@@ -266,6 +276,8 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 364、修复va core进程死亡后,APP可能打不开的问题
363、增加未安装插件时无法启动的错误日志
+
+2017年 12月 至 2021年 9月 210 日 商业版代码更新内容(下拉打开) **2021年 8月22号 至 2021年 9月20号 商业版代码更新内容** @@ -282,9 +294,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 352、修复targetSdk为30时,sdcard无法访问的问题
351、编译脚本中使用cmake替换gradle task
350、移除过时文档
- -
-2017年 12月 至 2021年 8月 21 日 商业版代码更新内容(下拉打开) **2021年 8月7号 至 2021年 8月21号 商业版代码更新内容** From 6c03afa99f5b3add1df2305daf5f7917621ae13b Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 29 Dec 2021 09:27:09 +0800 Subject: [PATCH 216/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2ab7daaad..f9c21e8fe 100644 --- a/README.md +++ b/README.md @@ -258,9 +258,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 379、Android 12.0第一轮适配已完成
378、Demo App在11.0上增加文件权限检测
377、修复静态广播接收者在独立进程无法接收广播的问题
-376、修复微信微信第一次登录可能crash问题
+376、修复微信第一次登录可能crash问题
375、修复部分APP无法显示头像问题
-374、修复部分OPPO手机上打不开问题
+374、修复在部分OPPO手机上打不开问题
**2021年 9月21号 至 2021年 11月23号 商业版代码更新内容** From d8d1e3829a6c7a82b01af752fc86676cf75d7723 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 21 Jan 2022 09:30:01 +0800 Subject: [PATCH 217/334] Update README.md --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f9c21e8fe..6be9d002f 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2021年商业版代码更新详细 ------ +**2021年 12月30号 至 2022年 1月21号 商业版代码更新内容** + +382、Sandhook适配12.0
+381、修复Sandhook在部分11.0上不生效的问题
+380、增加编译选项VA_FULL_EXT控制是否将VA源码编译到插件,满足加固场景。
**2021年 11月24号 至 2021年 12月29号 商业版代码更新内容** @@ -262,6 +267,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 375、修复部分APP无法显示头像问题
374、修复在部分OPPO手机上打不开问题
+
+2017年 12月 至 2021年 11月 23 日 商业版代码更新内容(下拉打开) + **2021年 9月21号 至 2021年 11月23号 商业版代码更新内容** 373、修复WhatsApp在360手机上黑屏问题
@@ -276,9 +284,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 364、修复va core进程死亡后,APP可能打不开的问题
363、增加未安装插件时无法启动的错误日志
-
-2017年 12月 至 2021年 9月 210 日 商业版代码更新内容(下拉打开) - **2021年 8月22号 至 2021年 9月20号 商业版代码更新内容** 362、横屏重新适配
From 3ccab83a63d8551bb712f5049803521ac6c4a8a5 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 21 Jan 2022 09:44:16 +0800 Subject: [PATCH 218/334] Update README_eng.md --- README_eng.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/README_eng.md b/README_eng.md index c519e0b35..e67d31f0b 100644 --- a/README_eng.md +++ b/README_eng.md @@ -247,8 +247,28 @@ Major updates of the business version 2017 - 2021 Business Edition Code Update Details ------ -**September 21, 2021 to October 27, 2021 Business Edition Code Updates** +**December 30, 2021 to January 21, 2022 Business Edition Code Updates** +382、Sandhook adapter 12.0
+381、Fix the problem that Sandhook does not work on some 11.0
+380、Added the compile option VA_FULL_EXT to control whether to compile the VA source code into the VA-EXT
+ +**November 24, 2021 to December 29, 2021 Business Edition Code Updates** + +379、Adapter Android 12.0
+378、Add file permission check
+377、Fixed the issue that static broadcast receivers could not receive broadcasts in independent processes
+376、Fix the problem that WeChat may crash when logging in for the first time
+375、Fix some App some apps could not display avatars
+374、Fix VA crash on some oppo devices
+ +
+December 2017 to August 21, 2021 Business Edition code updates (Drop down to open) + +**September 21, 2021 to November 23, 2021 Business Edition Code Updates** + +373、Fix WhatsApp crash on some devices
+372、Add broadcast test for VA
371、Fix the compatibility problem of Tik Tok Speed version
370、Fix readlinkat return value precision
369、Fix the problem of installing APP from outside, not referencing org.apache.http.legacy
@@ -276,8 +296,6 @@ Major updates of the business version 351、Use cmake to replace gradle task in compile script.
350、Remove obsolete documents
-
-December 2017 to August 21, 2021 Business Edition code updates (Drop down to open) **August 7, 2021 to August 21, 2021 Business Edition code Updates** From f36470e0960fee0276091e358722466b5bc54a6f Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 12 Mar 2022 09:16:48 +0800 Subject: [PATCH 219/334] Update README.md --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6be9d002f..547ab1bd7 100644 --- a/README.md +++ b/README.md @@ -252,12 +252,27 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2021年商业版代码更新详细 ------ +**2021年 1月22号 至 2022年 3月12号 商业版代码更新内容** + +390、修复华为手机上StorageManager没有被hook的问题
+389、修复最新版微信无法从SD卡启动的问题
+388、PackageInfo中增加对requestedPermissionsFlags字段的处理
+387、新增VSettingsProvider,避免内置应用没有权限操作settings provider导致异常
+386、修复微信等APP启动黑屏,ANR等问题
+385、新增对MediaProvider的hook
+384、新增对插件shareUserId的处理,从而可以配置将插件的数据放到主包中。
+383、修复Android 12权限处理适配
+ **2021年 12月30号 至 2022年 1月21号 商业版代码更新内容** 382、Sandhook适配12.0
381、修复Sandhook在部分11.0上不生效的问题
380、增加编译选项VA_FULL_EXT控制是否将VA源码编译到插件,满足加固场景。
+ +
+2017年 12月 至 2021年 12月 29 日 商业版代码更新内容(下拉打开) + **2021年 11月24号 至 2021年 12月29号 商业版代码更新内容** 379、Android 12.0第一轮适配已完成
@@ -267,8 +282,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 375、修复部分APP无法显示头像问题
374、修复在部分OPPO手机上打不开问题
-
-2017年 12月 至 2021年 11月 23 日 商业版代码更新内容(下拉打开) **2021年 9月21号 至 2021年 11月23号 商业版代码更新内容** From 831990471230b8546ff285c677727c7ef51b2f1c Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 12 Mar 2022 09:19:09 +0800 Subject: [PATCH 220/334] Update README.md --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 547ab1bd7..cba4ae946 100644 --- a/README.md +++ b/README.md @@ -254,13 +254,14 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, **2021年 1月22号 至 2022年 3月12号 商业版代码更新内容** -390、修复华为手机上StorageManager没有被hook的问题
-389、修复最新版微信无法从SD卡启动的问题
-388、PackageInfo中增加对requestedPermissionsFlags字段的处理
-387、新增VSettingsProvider,避免内置应用没有权限操作settings provider导致异常
-386、修复微信等APP启动黑屏,ANR等问题
-385、新增对MediaProvider的hook
-384、新增对插件shareUserId的处理,从而可以配置将插件的数据放到主包中。
+391、修复华为手机上StorageManager没有被hook的问题
+390、修复最新版微信无法从SD卡启动的问题
+389、PackageInfo中增加对requestedPermissionsFlags字段的处理
+388、新增VSettingsProvider,避免内置应用没有权限操作settings provider导致异常
+387、修复微信等APP启动黑屏,ANR等问题
+386、新增对MediaProvider的hook
+385、新增对插件shareUserId的处理,从而可以配置将插件的数据放到主包中
+384、新增可以配置是否将Tinker禁用
383、修复Android 12权限处理适配
**2021年 12月30号 至 2022年 1月21号 商业版代码更新内容** From 7a262a32a2a78e80e715e75bbeceb80954efca41 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 4 Apr 2022 19:03:16 +0800 Subject: [PATCH 221/334] Update README.md --- README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cba4ae946..5adcf1640 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,16 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2021年商业版代码更新详细 ------ + +**2021年 3月13号 至 2022年 4月5号 商业版代码更新内容** + +396、新增功能:在VA中实现内置media provider,以支持媒体库隔离等需求
+395、修复微信/QQ使用语音时崩溃
+394、蓝牙崩溃问题适配
+393、增加部分Log
+392、删除一些无用代码
+ + **2021年 1月22号 至 2022年 3月12号 商业版代码更新内容** 391、修复华为手机上StorageManager没有被hook的问题
@@ -264,6 +274,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 384、新增可以配置是否将Tinker禁用
383、修复Android 12权限处理适配
+
+2017年 12月 至 2022年 1月 21 日 商业版代码更新内容(下拉打开) + + + **2021年 12月30号 至 2022年 1月21号 商业版代码更新内容** 382、Sandhook适配12.0
@@ -271,9 +286,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 380、增加编译选项VA_FULL_EXT控制是否将VA源码编译到插件,满足加固场景。
-
-2017年 12月 至 2021年 12月 29 日 商业版代码更新内容(下拉打开) - **2021年 11月24号 至 2021年 12月29号 商业版代码更新内容** 379、Android 12.0第一轮适配已完成
From 5870816f1aeb32b496b87e391066e73b80d6d0fb Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 4 Apr 2022 19:03:56 +0800 Subject: [PATCH 222/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5adcf1640..62e46d0e5 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
-2017年-2021年商业版代码更新详细 +2017年-2022年商业版代码更新详细 ------ From 6311050a9b52811c784d5d4d2c57ff8d2b636396 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 4 Apr 2022 19:05:10 +0800 Subject: [PATCH 223/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 62e46d0e5..d1048ca6e 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ -**2021年 3月13号 至 2022年 4月5号 商业版代码更新内容** +**2022年 3月13号 至 2022年 4月5号 商业版代码更新内容** 396、新增功能:在VA中实现内置media provider,以支持媒体库隔离等需求
395、修复微信/QQ使用语音时崩溃
@@ -262,7 +262,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 392、删除一些无用代码
-**2021年 1月22号 至 2022年 3月12号 商业版代码更新内容** +**2022年 1月22号 至 2022年 3月12号 商业版代码更新内容** 391、修复华为手机上StorageManager没有被hook的问题
390、修复最新版微信无法从SD卡启动的问题
From 5053a1fa0759f2ca74762e5a94d1569ef4b9aa07 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 27 Apr 2022 10:53:36 +0800 Subject: [PATCH 224/334] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index d1048ca6e..c2fc909f3 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ +**2022年 4月5号 至 2022年 4月27号 商业版代码更新内容** + +397、去掉sandhook中一些多余的hook代码,避免某些APP无法启动
+ + **2022年 3月13号 至 2022年 4月5号 商业版代码更新内容** 396、新增功能:在VA中实现内置media provider,以支持媒体库隔离等需求
From 126d21ee1f1b73fbb7342a5a1ada27e0a371d2ba Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 31 May 2022 10:15:26 +0800 Subject: [PATCH 225/334] Update README.md --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c2fc909f3..ac20a9484 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,12 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ +**2022年 4月28号 至 2022年 5月31号 商业版代码更新内容** + +399、修复onGetCallingUid hook引起的崩溃问题
+398、修复微信8.0.22启动崩溃的问题
+ + **2022年 4月5号 至 2022年 4月27号 商业版代码更新内容** 397、去掉sandhook中一些多余的hook代码,避免某些APP无法启动
@@ -267,6 +273,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 392、删除一些无用代码
+
+2017年 12月 至 2022年 3月 12 日 商业版代码更新内容(下拉打开) + **2022年 1月22号 至 2022年 3月12号 商业版代码更新内容** 391、修复华为手机上StorageManager没有被hook的问题
@@ -279,10 +288,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 384、新增可以配置是否将Tinker禁用
383、修复Android 12权限处理适配
-
-2017年 12月 至 2022年 1月 21 日 商业版代码更新内容(下拉打开) - - **2021年 12月30号 至 2022年 1月21号 商业版代码更新内容** From 45152ef0abfde562adb4fea0f907aef658deaecc Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 8 Jul 2022 10:33:40 +0800 Subject: [PATCH 226/334] Update README.md --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ac20a9484..125f4b287 100644 --- a/README.md +++ b/README.md @@ -252,12 +252,19 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2022年商业版代码更新详细 ------ +**2022年 6月1号 至 2022年 7月8号 商业版代码更新内容** + +401、修复开启虚拟储存后文件路径的处理问题
+400、修复12.0上Notification没有提示的问题
**2022年 4月28号 至 2022年 5月31号 商业版代码更新内容** 399、修复onGetCallingUid hook引起的崩溃问题
398、修复微信8.0.22启动崩溃的问题
+
+2017年 12月 至 2022年 4月 27 日 商业版代码更新内容(下拉打开) + **2022年 4月5号 至 2022年 4月27号 商业版代码更新内容** @@ -273,9 +280,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 392、删除一些无用代码
-
-2017年 12月 至 2022年 3月 12 日 商业版代码更新内容(下拉打开) - **2022年 1月22号 至 2022年 3月12号 商业版代码更新内容** 391、修复华为手机上StorageManager没有被hook的问题
From ebcbf000e3d1dbe4cd447ea97fecdc0ee7df99a7 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 25 Jul 2022 18:38:07 +0800 Subject: [PATCH 227/334] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 125f4b287..547e49ea8 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ VA的其他特性 进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 - 全版本支持
-支持5.0-12.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 +支持5.0-13.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 - 易扩展与集成
VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 @@ -180,6 +180,7 @@ VA已被**上百家**企业进行了广泛测试,包含**数十家上市公司 10.0 | 支持 11.0 | 支持 12.0 | 支持 +13.0 | 支持
@@ -252,6 +253,10 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2022年商业版代码更新详细 ------ +**2022年 7月9号 至 2022年 7月26号 商业版代码更新内容** + +402、Android 13.0适配
+ **2022年 6月1号 至 2022年 7月8号 商业版代码更新内容** 401、修复开启虚拟储存后文件路径的处理问题
From 19694987c6bb034cbdfd3f33073b28b26636934e Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 25 Jul 2022 18:39:18 +0800 Subject: [PATCH 228/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 547e49ea8..b02941bd9 100644 --- a/README.md +++ b/README.md @@ -237,7 +237,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 商业版主要更新 ------ -1. 兼容最新Android S +1. 兼容最新Android 13.0 2. 不易被杀毒软件误报 3. 框架优化,性能大幅提升 4. 手机系统及APP兼容性大幅提升 From 5d6c29002f0486945f2f0d0e2e31323d7063dbc0 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 25 Jul 2022 18:42:33 +0800 Subject: [PATCH 229/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b02941bd9..7cb709779 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 7. 内置`XPosed Hook`框架 8. 增加定位模拟代码 9. 增加改机代码 -10. 其他近400项问题的修复和改进,详情请见下表 +10. 其他400+项问题的修复和改进,详情请见下表
From b34b963cb291ca4be95717e3c5cc8840d242d221 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 19 Aug 2022 16:58:25 +0800 Subject: [PATCH 230/334] Update README.md --- README.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7cb709779..47092ff32 100644 --- a/README.md +++ b/README.md @@ -253,23 +253,35 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2022年商业版代码更新详细 ------ -**2022年 7月9号 至 2022年 7月26号 商业版代码更新内容** +**2022年 7月27号 至 2022年 8月19号 商业版代码更新内容** -402、Android 13.0适配
+413、Android 13.0继续适配
+412、主版调整为64bit
+411、修复某些华为手机上App无法打开的问题
+410、修复OPPO 13.0上无法打开应用的问题
+409、修复百度语音TTS的调用问题
+408、修复数据隔离后仍可以访问sdcard根目录的问题
+407、修复鸿蒙手机上的崩溃问题
+406、修复Debug模式下Hook失效问题
+405、添加对BinderInvocationStub的混淆处理,避免混淆后崩溃问题
+404、修复Native层调用free函数可能导致崩溃的问题
+403、修复微信由于虚拟文件系统导致的崩溃问题
-**2022年 6月1号 至 2022年 7月8号 商业版代码更新内容** +**2022年 7月9号 至 2022年 7月26号 商业版代码更新内容** + +402、Android 13.0适配
401、修复开启虚拟储存后文件路径的处理问题
400、修复12.0上Notification没有提示的问题
+
+2017年 12月 至 2022年 5月 31 日 商业版代码更新内容(下拉打开) + **2022年 4月28号 至 2022年 5月31号 商业版代码更新内容** 399、修复onGetCallingUid hook引起的崩溃问题
398、修复微信8.0.22启动崩溃的问题
-
-2017年 12月 至 2022年 4月 27 日 商业版代码更新内容(下拉打开) - **2022年 4月5号 至 2022年 4月27号 商业版代码更新内容** From ed54172e8cad3734a4ce356d4b0d232e6ad43130 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 19 Aug 2022 17:03:01 +0800 Subject: [PATCH 231/334] Update README_eng.md --- README_eng.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README_eng.md b/README_eng.md index e67d31f0b..3eafd8911 100644 --- a/README_eng.md +++ b/README_eng.md @@ -131,7 +131,7 @@ VA Other features Process-level "virtual machine", VA's unique implementation model makes its performance almost the same as that of the native APP, and does not need a long startup of ordinary virtual machines. - Full version support
-Support 5.0-12.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. +Support 5.0-13.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. - Easy Expansion and Integration
The integration of VA is similar to the normal Android library, even if your APP has been online, you can conveniently integrate VA and enjoy the capability brought by VA. @@ -176,6 +176,7 @@ System version | Whether to support 10.0 | support 11.0 | support 12.0 | support +13.0 | support
From 91a217787775a3a3676c770c4605903bc5803cb5 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 19 Aug 2022 17:19:36 +0800 Subject: [PATCH 232/334] Update README_eng.md --- README_eng.md | 61 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/README_eng.md b/README_eng.md index 3eafd8911..37326bfd8 100644 --- a/README_eng.md +++ b/README_eng.md @@ -232,7 +232,7 @@ If you use VirtualApp for **internal use, business profit or upload it to the ap Major updates of the business version ------ -1. Compatible with the latest Android S +1. Support Android 13.0 2. Not easily misreported by anti-virus software 3. Framework optimization, performance greatly improved 4. Mobile system and APP compatibility greatly improved @@ -247,6 +247,62 @@ Major updates of the business version 2017 - 2021 Business Edition Code Update Details ------ +**July 27, 2022 to August 19, 2022 Business Edition Code Updatest** + +413. Android 13.0 continues to adapt
+412. Adjust the main version to 64bit
+411. Fix the problem that the App cannot be opened on some Huawei mobile phones
+410. Fix the problem that the application cannot be opened on OPPO 13.0
+409. Fix the calling problem of Baidu Voice TTS
+408. Fix the problem that the root directory of sdcard can still be accessed after data isolation
+407. Repair the crash problem on Harmony mobile phone
+406. Fix the problem of Hook failure in Debug mode
+405. Add obfuscation of BinderInvocationStub to avoid the crash problem after obfuscation
+404. Fix the problem that the native layer may crash when calling the free function
+403. Fix the crash problem of WeChat due to the virtual file system
+ + +**July 9, 2022 to July 26, 2022 Business Edition Code Updatest** + +402, Android 13.0 adaptation
+401. Fix the problem of file path processing after virtual storage is enabled
+400. Fix the problem that Notification does not prompt on 12.0
+ +
+December 2017 to May 31, 2022 Business Edition code updates (Drop down to open)
+ + +**April 28, 2022 to May 31, 2022 Business Edition Code Updatest** + +399. Fix the crash caused by onGetCallingUid hook
+398. Repair the problem of WeChat 8.0.22 startup crash
+ + +**April 5, 2022 to April 27, 2022 Business Edition Code Updatest** + +397. Remove some redundant hook codes in sandhook to prevent some apps from failing to start
+ + +**March 13, 2022 to April 5, 2022 Business Edition Code Updatest** + +396. New function: Implement built-in media provider in VA to support media library isolation and other requirements
+395. Fix WeChat/QQ crash when using voice
+394. Bluetooth crash problem adaptation
+393. Add some Log
+392. Delete some useless codes
+ + +**January 22, 2022 to March 12, 2022 Business Edition Code Updatest** + +391. Fix the problem that StorageManager is not hooked on Huawei mobile phones
+390. Fix the problem that the latest version of WeChat cannot be started from the SD card
+389. Add the processing of the requestedPermissionsFlags field in PackageInfo
+388. Added VSettingsProvider to avoid exceptions caused by built-in applications without permission to operate settings provider
+387. Fix WeChat and other APP startup black screen, ANR and other problems
+386. Add hook to MediaProvider
+385. Added the processing of plug-in shareUserId, so that the data of the plug-in can be configured to be placed in the main package
+384. Added option to configure whether to disable Tinker
+383. Fix Android 12 permission processing adaptation
**December 30, 2021 to January 21, 2022 Business Edition Code Updates** @@ -263,9 +319,6 @@ Major updates of the business version 375、Fix some App some apps could not display avatars
374、Fix VA crash on some oppo devices
-
-December 2017 to August 21, 2021 Business Edition code updates (Drop down to open) - **September 21, 2021 to November 23, 2021 Business Edition Code Updates** 373、Fix WhatsApp crash on some devices
From c276770fe55bfd926b03ee73a9dd622b586001b5 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 19 Aug 2022 17:28:13 +0800 Subject: [PATCH 233/334] Update README_eng.md --- README_eng.md | 67 ++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/README_eng.md b/README_eng.md index 37326bfd8..cdf6073e5 100644 --- a/README_eng.md +++ b/README_eng.md @@ -249,60 +249,61 @@ Major updates of the business version ------ **July 27, 2022 to August 19, 2022 Business Edition Code Updatest** -413. Android 13.0 continues to adapt
-412. Adjust the main version to 64bit
-411. Fix the problem that the App cannot be opened on some Huawei mobile phones
-410. Fix the problem that the application cannot be opened on OPPO 13.0
-409. Fix the calling problem of Baidu Voice TTS
-408. Fix the problem that the root directory of sdcard can still be accessed after data isolation
-407. Repair the crash problem on Harmony mobile phone
-406. Fix the problem of Hook failure in Debug mode
-405. Add obfuscation of BinderInvocationStub to avoid the crash problem after obfuscation
-404. Fix the problem that the native layer may crash when calling the free function
-403. Fix the crash problem of WeChat due to the virtual file system
+**July 27, 2022 to August 19, 2022 Business Edition Code Updatest** + +413、Android 13.0 continues to adapt
+412、Adjust the main version to 64bit
+411、Fix the problem that the App cannot be opened on some Huawei mobile phones
+410、Fix the problem that the application cannot be opened on OPPO 13.0
+409、Fix the calling problem of Baidu Voice TTS
+408、Fix the problem that the root directory of sdcard can still be accessed after data isolation
+407、Repair the crash problem on Harmony mobile phone
+406、Fix the problem of Hook failure in Debug mode
+405、Add obfuscation of BinderInvocationStub to avoid the crash problem after obfuscation
+404、Fix the problem that the native layer may crash when calling the free function
+403、Fix the crash problem of WeChat due to the virtual file system
**July 9, 2022 to July 26, 2022 Business Edition Code Updatest** -402, Android 13.0 adaptation
-401. Fix the problem of file path processing after virtual storage is enabled
-400. Fix the problem that Notification does not prompt on 12.0
+402、Android 13.0 adaptation
+401、Fix the problem of file path processing after virtual storage is enabled
+400、Fix the problem that Notification does not prompt on 12.0
-December 2017 to May 31, 2022 Business Edition code updates (Drop down to open)
- +December 2017 to May 31, 2022 Business Edition code updates (Drop down to open) **April 28, 2022 to May 31, 2022 Business Edition Code Updatest** -399. Fix the crash caused by onGetCallingUid hook
-398. Repair the problem of WeChat 8.0.22 startup crash
+399、Fix the crash caused by onGetCallingUid hook
+398、Repair the problem of WeChat 8.0.22 startup crash
**April 5, 2022 to April 27, 2022 Business Edition Code Updatest** -397. Remove some redundant hook codes in sandhook to prevent some apps from failing to start
+397、Remove some redundant hook codes in sandhook to prevent some apps from failing to start
**March 13, 2022 to April 5, 2022 Business Edition Code Updatest** -396. New function: Implement built-in media provider in VA to support media library isolation and other requirements
-395. Fix WeChat/QQ crash when using voice
-394. Bluetooth crash problem adaptation
-393. Add some Log
-392. Delete some useless codes
+396、New function: Implement built-in media provider in VA to support media library isolation and other requirements
+395、Fix WeChat/QQ crash when using voice
+394、Bluetooth crash problem adaptation
+393、Add some Log
+392、Delete some useless codes
**January 22, 2022 to March 12, 2022 Business Edition Code Updatest** -391. Fix the problem that StorageManager is not hooked on Huawei mobile phones
-390. Fix the problem that the latest version of WeChat cannot be started from the SD card
-389. Add the processing of the requestedPermissionsFlags field in PackageInfo
-388. Added VSettingsProvider to avoid exceptions caused by built-in applications without permission to operate settings provider
-387. Fix WeChat and other APP startup black screen, ANR and other problems
-386. Add hook to MediaProvider
-385. Added the processing of plug-in shareUserId, so that the data of the plug-in can be configured to be placed in the main package
-384. Added option to configure whether to disable Tinker
-383. Fix Android 12 permission processing adaptation
+391、Fix the problem that StorageManager is not hooked on Huawei mobile phones
+390、Fix the problem that the latest version of WeChat cannot be started from the SD card
+389、Add the processing of the requestedPermissionsFlags field in PackageInfo
+388、Added VSettingsProvider to avoid exceptions caused by built-in applications without permission to operate settings provider
+387、Fix WeChat and other APP startup black screen, ANR and other problems
+386、Add hook to MediaProvider
+385、Added the processing of plug-in shareUserId, so that the data of the plug-in can be configured to be placed in the main package
+384、Added option to configure whether to disable Tinker
+383、Fix Android 12 permission processing adaptation
**December 30, 2021 to January 21, 2022 Business Edition Code Updates** From 6015a569ffdcf719668513e3206648dbd2b8a188 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 19 Aug 2022 17:28:40 +0800 Subject: [PATCH 234/334] Update README_eng.md --- README_eng.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README_eng.md b/README_eng.md index cdf6073e5..1f7c545f8 100644 --- a/README_eng.md +++ b/README_eng.md @@ -249,8 +249,6 @@ Major updates of the business version ------ **July 27, 2022 to August 19, 2022 Business Edition Code Updatest** -**July 27, 2022 to August 19, 2022 Business Edition Code Updatest** - 413、Android 13.0 continues to adapt
412、Adjust the main version to 64bit
411、Fix the problem that the App cannot be opened on some Huawei mobile phones
From 097a9fac6e504f3a1e752d704ff97d526ac7d0aa Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 8 Oct 2022 11:55:34 +0800 Subject: [PATCH 235/334] Update README.md --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 47092ff32..035dd1d18 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,19 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2022年商业版代码更新详细 ------ + +**2022年 8月20号 至 2022年 10月8号 商业版代码更新内容** + +422、新功能:增加启动插件Activity代理,绕过后台5s限制
+421、修复Provider在10.0+上crash的问题
+420、适配最新版微信
+419、适配克隆时不显示sdcard上的APK
+418、适配12.0+上PendingIntent Flags必须为FLAG_UPDATE_CURRENT/FLAG_IMMUTABLE
+417、修复MediaProvider因为ACCESS_MEDIA_LOCATION 权限检查导致的crash
+416、修复12.0+上debug模式下hook失败的问题
+415、适配在Multi User账户下crash的问题
+414、适配由于后台限制导致VA Core启动插件中Activity失败的问题
+ **2022年 7月27号 至 2022年 8月19号 商业版代码更新内容** 413、Android 13.0继续适配
@@ -267,6 +280,8 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 404、修复Native层调用free函数可能导致崩溃的问题
403、修复微信由于虚拟文件系统导致的崩溃问题
+
+2017年 12月 至 2022年 7月 26 日 商业版代码更新内容(下拉打开) **2022年 7月9号 至 2022年 7月26号 商业版代码更新内容** @@ -274,8 +289,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 401、修复开启虚拟储存后文件路径的处理问题
400、修复12.0上Notification没有提示的问题
-
-2017年 12月 至 2022年 5月 31 日 商业版代码更新内容(下拉打开) **2022年 4月28号 至 2022年 5月31号 商业版代码更新内容** From dd75995f90669dcfc252903c6f05c8a30eebc629 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 7 Nov 2022 22:29:08 +0800 Subject: [PATCH 236/334] Update README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 035dd1d18..853a5dcc4 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,16 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ +**2022年10月9号 至 2022年 11月8号 商业版代码更新内容** + +429、修复当VA_AUTHORITY_PREFIX不等于包名时找不到Provider的问题:"Failed to find provider info ..."
+428、getPermissionActivityIntent处理
+427、修复特殊情况下,检查权限无限弹窗
+426、强调Intent使用外部通讯录(如果被第三方接管,建议使用外部可见)
+425、新增几个Java API适配
+424、修复修复部分后台Activity跳转问题
+423、修复在10.0+上后台Activity无法启动的问题
+ **2022年 8月20号 至 2022年 10月8号 商业版代码更新内容** 422、新功能:增加启动插件Activity代理,绕过后台5s限制
From 6640747fea5c38a8ad40d201560aa30efeeb4d31 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 7 Nov 2022 22:29:57 +0800 Subject: [PATCH 237/334] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 853a5dcc4..099a9cdca 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,10 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 415、适配在Multi User账户下crash的问题
414、适配由于后台限制导致VA Core启动插件中Activity失败的问题
+ +
+2017年 12月 至 2022年 8月 19 日 商业版代码更新内容(下拉打开) + **2022年 7月27号 至 2022年 8月19号 商业版代码更新内容** 413、Android 13.0继续适配
@@ -290,8 +294,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 404、修复Native层调用free函数可能导致崩溃的问题
403、修复微信由于虚拟文件系统导致的崩溃问题
-
-2017年 12月 至 2022年 7月 26 日 商业版代码更新内容(下拉打开) **2022年 7月9号 至 2022年 7月26号 商业版代码更新内容** From 89fb2f47210a2d299518fca73b82cb14c337e822 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 24 Nov 2022 11:43:24 +0800 Subject: [PATCH 238/334] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 099a9cdca..d3e5a15a3 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
负责人:张总
-手机:130-321-77777
微信:10890

From 5443a6eb9aad8d717ef41975baee5ca8844425a7 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 24 Nov 2022 11:44:35 +0800 Subject: [PATCH 239/334] Update README_eng.md --- README_eng.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README_eng.md b/README_eng.md index 1f7c545f8..f53ce6611 100644 --- a/README_eng.md +++ b/README_eng.md @@ -216,7 +216,6 @@ VirtualApp virtual machine technology belongs to: Jining Luohe Network Technolog
Person in charge: Mr. Zhang
-Telephone: +86 130-321-77777
WeChat:10890

From 70e7d7a31a2f7063a984dd35b183381f4d508d21 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 8 Dec 2022 15:14:55 +0800 Subject: [PATCH 240/334] Update README.md --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d3e5a15a3..83c7f12ed 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,12 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ +**2022年11月9号 至 2022年 12月8号 商业版代码更新内容** + +432、修复Facebook在某些情况下无法启动的问题
+431、启动外部App时,排除对VA自身的判断
+430、修复queryIntentServices过滤规则
+ **2022年10月9号 至 2022年 11月8号 商业版代码更新内容** 429、修复当VA_AUTHORITY_PREFIX不等于包名时找不到Provider的问题:"Failed to find provider info ..."
@@ -263,6 +269,10 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 424、修复修复部分后台Activity跳转问题
423、修复在10.0+上后台Activity无法启动的问题
+ +
+2017年 12月 至 2022年 10 月 8 日 商业版代码更新内容(下拉打开) + **2022年 8月20号 至 2022年 10月8号 商业版代码更新内容** 422、新功能:增加启动插件Activity代理,绕过后台5s限制
@@ -276,9 +286,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 414、适配由于后台限制导致VA Core启动插件中Activity失败的问题
-
-2017年 12月 至 2022年 8月 19 日 商业版代码更新内容(下拉打开) - **2022年 7月27号 至 2022年 8月19号 商业版代码更新内容** 413、Android 13.0继续适配
From 91123b839055279aac7edecb184572358d930bc2 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 26 Jan 2023 10:26:47 +0800 Subject: [PATCH 241/334] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 83c7f12ed..df5ed37f4 100644 --- a/README.md +++ b/README.md @@ -249,9 +249,10 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
-2017年-2022年商业版代码更新详细 +2017年-2023年商业版代码更新详细 ------ - +**2022年12月9号 至 2023年 1月26号 商业版代码更新内容** +432、修复PendingIntent flag处理问题
**2022年11月9号 至 2022年 12月8号 商业版代码更新内容** From ab2ad0e9b307d7a534eda79bffabaa3ca67cbbd3 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 26 Jan 2023 10:27:52 +0800 Subject: [PATCH 242/334] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index df5ed37f4..82cf9f639 100644 --- a/README.md +++ b/README.md @@ -252,7 +252,8 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ **2022年12月9号 至 2023年 1月26号 商业版代码更新内容** -432、修复PendingIntent flag处理问题
+ +433、修复PendingIntent flag处理问题
**2022年11月9号 至 2022年 12月8号 商业版代码更新内容** From 112ef04fc5ff32b4fdf0042cd5ffcd0bec3984c3 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 16 Feb 2023 10:21:08 +0800 Subject: [PATCH 243/334] Update README.md --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 82cf9f639..0ddfde874 100644 --- a/README.md +++ b/README.md @@ -251,6 +251,14 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ + +**2023年1月27号 至 2023年 2月16号 商业版代码更新内容** + +437、修复mOpPackageName空指针
+436、修复13.0上PackageManager几个flags参数导致的crash
+435、修复VAPP返回主页的Intent crash
+434、TelecomManagerStub API适配
+ **2022年12月9号 至 2023年 1月26号 商业版代码更新内容** 433、修复PendingIntent flag处理问题
@@ -261,6 +269,10 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 431、启动外部App时,排除对VA自身的判断
430、修复queryIntentServices过滤规则
+ +
+2017年 12月 至 2022年 11 月 8 日 商业版代码更新内容(下拉打开) + **2022年10月9号 至 2022年 11月8号 商业版代码更新内容** 429、修复当VA_AUTHORITY_PREFIX不等于包名时找不到Provider的问题:"Failed to find provider info ..."
@@ -272,9 +284,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 423、修复在10.0+上后台Activity无法启动的问题
-
-2017年 12月 至 2022年 10 月 8 日 商业版代码更新内容(下拉打开) - **2022年 8月20号 至 2022年 10月8号 商业版代码更新内容** 422、新功能:增加启动插件Activity代理,绕过后台5s限制
From 9004cc150a9a1aa22dd51f04ed7b6896f9b2d8b3 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 17 Mar 2023 16:13:36 +0800 Subject: [PATCH 244/334] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0ddfde874..2ec5d2bd1 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ +**2023年2月17号 至 2023年 3月17号 商业版代码更新内容** +438、修setPictureInPictureParams crash
+ **2023年1月27号 至 2023年 2月16号 商业版代码更新内容** 437、修复mOpPackageName空指针
From d4f828c335ccb96267d7bc9cdbe587054011277b Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 17 Mar 2023 16:14:09 +0800 Subject: [PATCH 245/334] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2ec5d2bd1..e10ba3112 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ **2023年2月17号 至 2023年 3月17号 商业版代码更新内容** + 438、修setPictureInPictureParams crash
**2023年1月27号 至 2023年 2月16号 商业版代码更新内容** From cc33e57e8360d20f2ec9729d2aed7053a2b82a1e Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 17 Mar 2023 16:15:17 +0800 Subject: [PATCH 246/334] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e10ba3112..422a2b60d 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 435、修复VAPP返回主页的Intent crash
434、TelecomManagerStub API适配
+
+2017年 12月 至 2023年 1 月 26 日 商业版代码更新内容(下拉打开) + **2022年12月9号 至 2023年 1月26号 商业版代码更新内容** 433、修复PendingIntent flag处理问题
@@ -274,9 +277,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 430、修复queryIntentServices过滤规则
-
-2017年 12月 至 2022年 11 月 8 日 商业版代码更新内容(下拉打开) - **2022年10月9号 至 2022年 11月8号 商业版代码更新内容** 429、修复当VA_AUTHORITY_PREFIX不等于包名时找不到Provider的问题:"Failed to find provider info ..."
From 5dc56cb7e86516abf28c116103d9954fcafa5d7c Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 27 Apr 2023 11:13:14 +0800 Subject: [PATCH 247/334] Update README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 422a2b60d..fe4b646e3 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,14 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ +**2023年3月18号 至 2023年 4月27号 商业版代码更新内容** + +443、修复GMS支持,修复各种crash,权限等问题
+442、修复GooglePlay无法打开的问题
+441、修复GooglePlay无法登录Google账号的问题
+440、修复Youtube,WhatsApp等APP无法登录Google账号的问题
+439、修复Facebook无法打开的问题
+ **2023年2月17号 至 2023年 3月17号 商业版代码更新内容** 438、修setPictureInPictureParams crash
From eeda53e188f479a10fa498b4228d4f8eb36a9484 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 24 May 2023 21:22:18 +0800 Subject: [PATCH 248/334] Update README.md --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fe4b646e3..e2fcc1578 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ VA的其他特性 进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 - 全版本支持
-支持5.0-13.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 +支持5.0-14.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 - 易扩展与集成
VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 @@ -181,6 +181,7 @@ VA已被**上百家**企业进行了广泛测试,包含**数十家上市公司 11.0 | 支持 12.0 | 支持 13.0 | 支持 +14.0 | 支持
@@ -236,7 +237,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 商业版主要更新 ------ -1. 兼容最新Android 13.0 +1. 兼容最新Android 14.0 2. 不易被杀毒软件误报 3. 框架优化,性能大幅提升 4. 手机系统及APP兼容性大幅提升 @@ -252,6 +253,10 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ +**2023年4月28号 至 2023年 5月25号 商业版代码更新内容** + +444、适配Android 14.0
+ **2023年3月18号 至 2023年 4月27号 商业版代码更新内容** 443、修复GMS支持,修复各种crash,权限等问题
@@ -260,6 +265,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 440、修复Youtube,WhatsApp等APP无法登录Google账号的问题
439、修复Facebook无法打开的问题
+ +
+2017年 12月 至 2023年 3 月 17 日 商业版代码更新内容(下拉打开) + + **2023年2月17号 至 2023年 3月17号 商业版代码更新内容** 438、修setPictureInPictureParams crash
@@ -270,9 +280,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 436、修复13.0上PackageManager几个flags参数导致的crash
435、修复VAPP返回主页的Intent crash
434、TelecomManagerStub API适配
- -
-2017年 12月 至 2023年 1 月 26 日 商业版代码更新内容(下拉打开) **2022年12月9号 至 2023年 1月26号 商业版代码更新内容** From 57e6741559fcca38ca8c068d07e618ecdad1b59d Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 7 Jun 2023 17:36:49 +0800 Subject: [PATCH 249/334] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e2fcc1578..6aa900a7e 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,12 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ +**2023年5月26号 至 2023年 6月7号 商业版代码更新内容** + +447、修复部分APP无法录音的问题
+446、修复从Sdcard安装APK失败的问题
+445、更改VA Demo包名
+ **2023年4月28号 至 2023年 5月25号 商业版代码更新内容** 444、适配Android 14.0
From a7c449eaafdd2b38b9cba6e8f1d005ba438ca7da Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 7 Jun 2023 17:38:01 +0800 Subject: [PATCH 250/334] Update README.md --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6aa900a7e..deac99337 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 444、适配Android 14.0
+
+2017年 12月 至 2023年 4 月 27 日 商业版代码更新内容(下拉打开) + **2023年3月18号 至 2023年 4月27号 商业版代码更新内容** 443、修复GMS支持,修复各种crash,权限等问题
@@ -272,10 +275,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 439、修复Facebook无法打开的问题
-
-2017年 12月 至 2023年 3 月 17 日 商业版代码更新内容(下拉打开) - - **2023年2月17号 至 2023年 3月17号 商业版代码更新内容** 438、修setPictureInPictureParams crash
From 02b31bb63210d056d2a830a9b748120c7162940b Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 29 Jun 2023 19:33:58 +0800 Subject: [PATCH 251/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index deac99337..ed74ddce0 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ -**2023年5月26号 至 2023年 6月7号 商业版代码更新内容** +**2023年5月26号 至 2023年 6月29号 商业版代码更新内容** 447、修复部分APP无法录音的问题
446、修复从Sdcard安装APK失败的问题
From 8950967c3a0f1cf8343550ec8080141c6da364a8 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 10 Jul 2023 09:50:16 +0800 Subject: [PATCH 252/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ed74ddce0..cd1630750 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ -**2023年5月26号 至 2023年 6月29号 商业版代码更新内容** +**2023年5月26号 至 2023年 7月10号 商业版代码更新内容** 447、修复部分APP无法录音的问题
446、修复从Sdcard安装APK失败的问题
From 9ea5d553edae7dbdb8b893b31760822f822f02ef Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 12 Jul 2023 17:18:05 +0800 Subject: [PATCH 253/334] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cd1630750..a8e538979 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,12 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ -**2023年5月26号 至 2023年 7月10号 商业版代码更新内容** +**2023年6月30号 至 2023年 7月12号 商业版代码更新内容** + +449、修复JobService unbind崩溃问题
+448、修复JobService persisted崩溃问题
+ +**2023年5月26号 至 2023年 6月29号 商业版代码更新内容** 447、修复部分APP无法录音的问题
446、修复从Sdcard安装APK失败的问题
From 5083e18b4b8c6aa392bc981064d5801479c92818 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 31 Jul 2023 17:54:55 +0800 Subject: [PATCH 254/334] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index a8e538979..903c5ebf3 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,11 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ +**2023年7月13号 至 2023年 8月1号 商业版代码更新内容** + +451、适配12.0+上蓝牙相关的10来个API
+450、适配UserManager相关的10来个API
+ **2023年6月30号 至 2023年 7月12号 商业版代码更新内容** 449、修复JobService unbind崩溃问题
From 8b550ef691e9500294a2b963c578faa540152565 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 15 Aug 2023 14:14:03 +0800 Subject: [PATCH 255/334] Update README.md --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 903c5ebf3..f4034aeb7 100644 --- a/README.md +++ b/README.md @@ -253,11 +253,23 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ +**2023年8月2号 至 2023年 8月15号 商业版代码更新内容** + +456、修复Twitter白屏的问题
+455、修复ContentProvider在12.0+上的适配问题
+454、修复微信在nova9z上崩溃的问题
+453、修复微信等APP发送定位时黑屏的问题
+452、编译SDK版本升级到14.0
+ **2023年7月13号 至 2023年 8月1号 商业版代码更新内容** 451、适配12.0+上蓝牙相关的10来个API
450、适配UserManager相关的10来个API
+
+2017年 12月 至 2023年 7 月 12 日 商业版代码更新内容(下拉打开) + + **2023年6月30号 至 2023年 7月12号 商业版代码更新内容** 449、修复JobService unbind崩溃问题
@@ -273,9 +285,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 444、适配Android 14.0
-
-2017年 12月 至 2023年 4 月 27 日 商业版代码更新内容(下拉打开) - **2023年3月18号 至 2023年 4月27号 商业版代码更新内容** 443、修复GMS支持,修复各种crash,权限等问题
From 696ab70d50c48df10181761157e458d1d0ede717 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 5 Sep 2023 15:47:38 +0800 Subject: [PATCH 256/334] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f4034aeb7..e6e57a2c4 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,13 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ +**2023年8月16号 至 2023年 9月5号 商业版代码更新内容** + +460、14.0上JobScheduler适配
+459、修复API broadcastIntentWithFeature
+458、修复WhatsApp验证跳转的问题
+457、内部Provider访问适配
+ **2023年8月2号 至 2023年 8月15号 商业版代码更新内容** 456、修复Twitter白屏的问题
@@ -269,7 +276,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,
2017年 12月 至 2023年 7 月 12 日 商业版代码更新内容(下拉打开) - **2023年6月30号 至 2023年 7月12号 商业版代码更新内容** 449、修复JobService unbind崩溃问题
From 6eccf79ec2e6e53d5e979971fc9677e13ee2c2f3 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 15 Sep 2023 16:30:30 +0800 Subject: [PATCH 257/334] Update README.md --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e6e57a2c4..b03506de7 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,13 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 2017年-2023年商业版代码更新详细 ------ + +**2023年9月6号 至 2023年 9月15号 商业版代码更新内容** + +463、14.0上JobScheduler API适配
+462、修复从sdcard上安装时signature可能获取的可能不是最旧的问题
+461、LocaleManager适配
+ **2023年8月16号 至 2023年 9月5号 商业版代码更新内容** 460、14.0上JobScheduler适配
@@ -260,6 +267,9 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 458、修复WhatsApp验证跳转的问题
457、内部Provider访问适配
+
+2017年 12月 至 2023年 8 月 15 日 商业版代码更新内容(下拉打开)
+ **2023年8月2号 至 2023年 8月15号 商业版代码更新内容** 456、修复Twitter白屏的问题
@@ -273,8 +283,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 451、适配12.0+上蓝牙相关的10来个API
450、适配UserManager相关的10来个API
-
-2017年 12月 至 2023年 7 月 12 日 商业版代码更新内容(下拉打开) **2023年6月30号 至 2023年 7月12号 商业版代码更新内容** From 2cee24eac658705c68a6e9e5bd85393cf34789a0 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 7 Oct 2023 14:10:40 +0800 Subject: [PATCH 258/334] Update README.md --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b03506de7..c660eb805 100644 --- a/README.md +++ b/README.md @@ -254,12 +254,24 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, ------ +**2023年9月16号 至 2023年 10月7号 商业版代码更新内容** + +469、移除已经废弃的虚拟定位代码
+468、修复WhatsApp 来电通知bug
+467、修复GMS相关问题
+466、修复WhatsApp无法跳过短息验证界面问题
+465、修复WhatsApp等部分APP启动后界面白屏问题
+464、适配Alarms 相关API + **2023年9月6号 至 2023年 9月15号 商业版代码更新内容** 463、14.0上JobScheduler API适配
462、修复从sdcard上安装时signature可能获取的可能不是最旧的问题
461、LocaleManager适配
+
+2017年 12月 至 2023年 8 月 5 日 商业版代码更新内容(下拉打开)
+ **2023年8月16号 至 2023年 9月5号 商业版代码更新内容** 460、14.0上JobScheduler适配
@@ -267,8 +279,6 @@ VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司, 458、修复WhatsApp验证跳转的问题
457、内部Provider访问适配
-
-2017年 12月 至 2023年 8 月 15 日 商业版代码更新内容(下拉打开)
**2023年8月2号 至 2023年 8月15号 商业版代码更新内容** From ee431f41854e06dfc7bfd7011bf84cf27fc9406b Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 11 Oct 2023 17:36:03 +0800 Subject: [PATCH 259/334] Update README_eng.md --- README_eng.md | 528 +------------------------------------------------- 1 file changed, 5 insertions(+), 523 deletions(-) diff --git a/README_eng.md b/README_eng.md index f53ce6611..89ffdb081 100644 --- a/README_eng.md +++ b/README_eng.md @@ -131,7 +131,7 @@ VA Other features Process-level "virtual machine", VA's unique implementation model makes its performance almost the same as that of the native APP, and does not need a long startup of ordinary virtual machines. - Full version support
-Support 5.0-13.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. +Support 5.0-14.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. - Easy Expansion and Integration
The integration of VA is similar to the normal Android library, even if your APP has been online, you can conveniently integrate VA and enjoy the capability brought by VA. @@ -177,6 +177,7 @@ System version | Whether to support 11.0 | support 12.0 | support 13.0 | support +14.0 | support
@@ -212,7 +213,7 @@ Please refer to the VA development documentation:[Development document](doc/VA License Instructions ------ -VirtualApp virtual machine technology belongs to: Jining Luohe Network Technology Co., LTD. It applied for several VirtualApp intellectual property rights from 2015 to 2021 and` is protected by the Intellectual property Law of the People's Republic of China`.When you need to use the code on Github, **please purchase a business license**,and receive the full source code of the latest VirtualApp business version.Hundreds of licensed customers are paying to use the business version of VirtualApp code, and the app integrated with VirtualApp code is launched more than 200 million times a day. Many Android engineers provided us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, VirtualApp Business Edition code has better performance and higher compatibility. `The company of that year will become one of them after obtaining the license, and enjoy the technological achievements after the continuous iteration. And we can interact and collaborate with our licensed customers operationally, technically and commercially.` +VirtualApp virtual machine technology belongs to: Jining Luohe Network Technology Co., LTD. It applied for several VirtualApp intellectual property rights from 2015 to 2023 and` is protected by the Intellectual property Law of the People's Republic of China`.When you need to use the code on Github, **please purchase a business license**,and receive the full source code of the latest VirtualApp business version.Hundreds of licensed customers are paying to use the business version of VirtualApp code, and the app integrated with VirtualApp code is launched more than 200 million times a day. Many Android engineers provided us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, VirtualApp Business Edition code has better performance and higher compatibility. `The company of that year will become one of them after obtaining the license, and enjoy the technological achievements after the continuous iteration. And we can interact and collaborate with our licensed customers operationally, technically and commercially.`
Person in charge: Mr. Zhang
@@ -231,7 +232,7 @@ If you use VirtualApp for **internal use, business profit or upload it to the ap Major updates of the business version ------ -1. Support Android 13.0 +1. Support Android 14.0 2. Not easily misreported by anti-virus software 3. Framework optimization, performance greatly improved 4. Mobile system and APP compatibility greatly improved @@ -240,531 +241,12 @@ Major updates of the business version 7. Built-in `XPosed Hook` framework 8. Add positioning mock code 9. Add code to change device -10. Nearly 400 other fixes and improvements, please see the following table for detail - +10. Nearly 500 other fixes and improvements
-2017 - 2021 Business Edition Code Update Details ------- -**July 27, 2022 to August 19, 2022 Business Edition Code Updatest** - -413、Android 13.0 continues to adapt
-412、Adjust the main version to 64bit
-411、Fix the problem that the App cannot be opened on some Huawei mobile phones
-410、Fix the problem that the application cannot be opened on OPPO 13.0
-409、Fix the calling problem of Baidu Voice TTS
-408、Fix the problem that the root directory of sdcard can still be accessed after data isolation
-407、Repair the crash problem on Harmony mobile phone
-406、Fix the problem of Hook failure in Debug mode
-405、Add obfuscation of BinderInvocationStub to avoid the crash problem after obfuscation
-404、Fix the problem that the native layer may crash when calling the free function
-403、Fix the crash problem of WeChat due to the virtual file system
-**July 9, 2022 to July 26, 2022 Business Edition Code Updatest** -402、Android 13.0 adaptation
-401、Fix the problem of file path processing after virtual storage is enabled
-400、Fix the problem that Notification does not prompt on 12.0
- -
-December 2017 to May 31, 2022 Business Edition code updates (Drop down to open) - -**April 28, 2022 to May 31, 2022 Business Edition Code Updatest** - -399、Fix the crash caused by onGetCallingUid hook
-398、Repair the problem of WeChat 8.0.22 startup crash
- - -**April 5, 2022 to April 27, 2022 Business Edition Code Updatest** - -397、Remove some redundant hook codes in sandhook to prevent some apps from failing to start
- - -**March 13, 2022 to April 5, 2022 Business Edition Code Updatest** - -396、New function: Implement built-in media provider in VA to support media library isolation and other requirements
-395、Fix WeChat/QQ crash when using voice
-394、Bluetooth crash problem adaptation
-393、Add some Log
-392、Delete some useless codes
- - -**January 22, 2022 to March 12, 2022 Business Edition Code Updatest** - -391、Fix the problem that StorageManager is not hooked on Huawei mobile phones
-390、Fix the problem that the latest version of WeChat cannot be started from the SD card
-389、Add the processing of the requestedPermissionsFlags field in PackageInfo
-388、Added VSettingsProvider to avoid exceptions caused by built-in applications without permission to operate settings provider
-387、Fix WeChat and other APP startup black screen, ANR and other problems
-386、Add hook to MediaProvider
-385、Added the processing of plug-in shareUserId, so that the data of the plug-in can be configured to be placed in the main package
-384、Added option to configure whether to disable Tinker
-383、Fix Android 12 permission processing adaptation
- -**December 30, 2021 to January 21, 2022 Business Edition Code Updates** - -382、Sandhook adapter 12.0
-381、Fix the problem that Sandhook does not work on some 11.0
-380、Added the compile option VA_FULL_EXT to control whether to compile the VA source code into the VA-EXT
- -**November 24, 2021 to December 29, 2021 Business Edition Code Updates** - -379、Adapter Android 12.0
-378、Add file permission check
-377、Fixed the issue that static broadcast receivers could not receive broadcasts in independent processes
-376、Fix the problem that WeChat may crash when logging in for the first time
-375、Fix some App some apps could not display avatars
-374、Fix VA crash on some oppo devices
- -**September 21, 2021 to November 23, 2021 Business Edition Code Updates** - -373、Fix WhatsApp crash on some devices
-372、Add broadcast test for VA
-371、Fix the compatibility problem of Tik Tok Speed version
-370、Fix readlinkat return value precision
-369、Fix the problem of installing APP from outside, not referencing org.apache.http.legacy
-368、Fix Huawei Nova 5i, 64-bit main package compatibility
-367、Fix external storage redirection issue on 11.0
-366、Fix the GMS login problem on 11.0
-365、Fix 11.0 some APP read and write sdcard error problem
-364、Fix the problem that APP may not open after the death of VA core process
-363、Add the error log that can't start when no plug-in is installed
- - -**August 22, 2021 to September 20, 2021 Business Edition Code Updates** - -362、Horizontal screen re-adaptation
-361、Fix the problem that some APPs cannot be opened after installation through file protocol
-360、Fix the problem of Intent data loss in the Intent passed to JobIntentService
-359、Fix the problem that the second call of JobIntentService does not work
-358、Fix the problem of crashing some APPs on Huawei cell phones
-357、Fix the game login problem on Xiaomi phone
-356、Fix the problem that some applications cannot be opened after reinforcement
-355、Add detection of associated start permission
-354、targetSdk 30 adaptation
-353、Fix the problem that some applications can't access the Internet when targetSdk is 30
-352、Fix the problem that sdcard can't be accessed when targetSdk is 30
-351、Use cmake to replace gradle task in compile script.
-350、Remove obsolete documents
- - -**August 7, 2021 to August 21, 2021 Business Edition code Updates** - -349、Tweak and optimize gradle script
-348、hidedenApiBypass support for Android R+
-347、targetSdk 30 support
-346、Fixthe bug that VIVO system service
-345、Fix the bug that VIVO phone can't use camera
-344、Fix dex loading abnormal state acquisition
-343、Fix libart.so path problem on Android R
-342、Fix the bug of Andoid Q+ delete notification
-341、Fix the permission check of APN uri
-340、Fix Android R suspend resume thread state
-339、Fix some hook failure cases in debug mode
-338、Fix some bugs of hook after R
- -**April 25, 2021 to August 6, 2021 Business Edition Code Updates** - -337、Fix the problem that some phones cannot upload avatars in Tan Tan
-336、Fix Android 10 Huawei device IO redirection problem
-335、Adjust the horizontal and vertical screen logic, reduce the occurrence of abnormalities
-334、Add the callback interface of Activity life cycle
-333、Fix the broadcasting problem of Android 12
-332、Fix the bug of abnormal status of some interfaces of WeChat
-331、Fix the support of Outlook, One drive, Teams, Zoom and other overseas APPs.
-330、Fix the bug Android 11 a permission request
-329、Fix the problem that some cocos2d engines only display half screen
-328、Fix the problem that WeChat can not send files under multi-user
-327、split apk support
-326、Android S support
- -**February 24, 2021 to April 24, 2021 Business Edition Code Updates** - -325、Adapt to multi-user environment
-324、Fix the compatibility problem of the new version of WeChat
-323、Compatible with more enterprise level reinforcement
-322、Support VAPP setting power source optimization
-321、Fix missing permission statement
-320、Fix the reference of android.test.base library on Android 11
-319、Optimize ext plugin judgment
-318、Optimize the selection of ABI during installation
-317、Fix Google docs crash on Android 11
- -**October 15, 2020 to February 23, 2021 Business Edition Code Updates** - -316、Solve the compatibility of the new version of Love Encryption, Bang Bang and other reinforcement
-315、Fix the problem of WhatsApp not showing cold boot Splash
-314、Optimize the recognition of system APP
-313、Improve the support in multi-user environment
-312、Solve the problem that ext plug-in is stuck in some cases
-311、Support Google Play to download APP in VirtualAPP
-310、Fix the problem that Android 11 QQ can not display pictures
-309、Compatible with Android 11 running Google Service
-308、Fix the problem that Android 11 can't run chromium
-307、Support Hook @CriticalNative Method
-306、Fix the problem that JDK 13 cannot be compiled and run
-305、Fix the problem that Service may crash in some cases
-304、Fix the problem that Android 11 cannot load private data of external storage
-303、Fix the problem that low version APP cannot use org.apache.http.legacy
-302、Fix the problem that the system task stack only shows the last one in some cases
-301、Improve the build script for different platforms
-300、Fix the problem that Android 11 cannot read obb
-299、Fix the problem that the software is not backward compatible
-298、Rebuild VAPP installation framework
-297、Rebuild virtual file system
-296、Fix the problem that WebView cannot be started under certain circumstances
-295、Fix the bug of VAPP uninstall and reinstall
-294、Fix the mobile game "LOL" login exception problem
-293、Support the installation of Splits APK
-292、Support dynamic configuration of the main package environment
-291、Fix the problem of 32-bit QQ calling 64-bit WeChat delay
-290、Fix the problem of Messenger calling Facebook crash
-289、Optimize the support of Google service framework
-288、Realize the new extension package synchronization mechanism
-287、Fix the exception problem of Android 11 official version
-286、Add system Package cache to optimize performance
-285、Fix the bug that the disabled component can still be queried by PMS
-284、Fix the problem of abnormal Launch behavior in some interfaces of WeChat
-283、Fix the bug that ContentProvider.getCallingPackage returns Host package name
-282、Fix the bug of uid virtualization and solve the problem that some app permission check fails
-281、Rewrite the implementation of PendingIntent, IntentSender
-280、Optimize process management, fix the long-standing probabilistic process deadlock problem
-279、Rewrite Service implementation, Service life cycle more accurate, not easy to be killed
- - -**September 13, 2020 to October 15, 2020 Business Edition Code Updates** - -278、Fix the problem that 64-bit APP cannot call 32-bit APP
-277、Fix the problem of loading HttpClient in Android R
-276、Fix the problem of a crash in Android R debug mode
- -**August 23, 2020 to September 12, 2020 Business Edition Code Updates** - -275、Add the missing service hook
-274、Fix the problem that Baidu Translate cannot be started
-273、Fix the problem that the split app downloaded by GP cannot be started
- -**July 10, 2020 to August 22, 2020 Business Edition Code Updates** - -272、Fix Service creation
-271、Add missing Hook for NotificationService
-270、Fix Yotube crash
- -**May 19, 2020 to July 9, 2020 Business Edition Code Updates** - -269、Preliminary adaptation of Android 11 beta1
-268、Fix the problem of multi space flashback in RED
-267、Fix the problem of "Application signature is tampered" reported by multi space of some APPs
- -**April 24, 2020 to May 18, 2020 Business Edition Code Updates** - -266、Fix sh call error
-265、Fix the problem that Facebook cannot be logged in in the latest version of 9.0 or above
-264、Help Enterprise WeChat to fix the problem that it can't take photos when starting virtual storage
-263、Fix the problem that 64-bit APP can't open Activity in some cases
- -**March 24, 2020 to April 23, 2020 Business Edition Code Updates** - -262、Fix the problem that Vivo device prompts to install game SDK
-261、Fix the problem that Android Q cannot load some system so
-260、Fix Huawei device microblog not responding
-259、Ignore crashes caused by unnecessary permission checks
-258、Fix the crash of WPS sharing files
-257、Flashback issue in some 10.0 devices
- -**March 7, 2020 to March 23, 2020 Business Edition Code Updates** - -256、Fix WeChat open two pages at the same time problem
-255、Fix the problem that WeChat login successfully but return to the login page
-254、Fix the problem that the latest version of QQ can not download attachments
-253、Update SandHook version
-252、Fix the problem of unsigned Apk installed above 9.0
-251、Fix the positioning problem of 10.0
- -**January 16, 2020 to March 6, 2020 Business Edition Code Updates** - -250、Tweak lib redirection logic
-249、Fix crash issue on Samsung 10.0 systems
-248、Fix hook exception in release build
-247、Add SandHook proguard rules
-246、Fix compatibility issue with VirtualApk in some APPs
-245、Fixed VA internal request to install apk failed
- -**December 26, 2019 to January 15, 2020 Business Edition Code Updates** - -244、Fix a missing hook in Android Q
-243、Disable AutoFill in Emui10
-242、Add new api to end all Activity
- -**December 15, 2019 to December 25, 2019 Business Edition Code Updates** - -241、Fix the problem that enterprise WeChat and other apps cannot be launched on Emui10
-240、Fix a possible crash in 4.x
-239、Upgrade SandHook to fix Hook for Thread class
-238、Fix the permission problem caused by some interfaces of Android Q
- -**November 20, 2019 to December 14, 2019 Business Edition Code Updates** - -237、Fix crash caused by Notification cache
-236、Fix classloader issue of high version Notification
- -**November 9, 2019 to November 19, 2019 Business Edition Code Updates** - -235、Fix ART Hook for Android 5.x
-234、Fix the deadlock problem caused by ART Hook
- -**November 2, 2019 to November 8, 2019 Business Edition Code Updates** - -233、Fix WPS, NetEase Mail, etc. crashing on Q devices
-232、Fix the problem that Tom Cat Run crashes on some Q devices
-231、Fix the problem that QQ crashes on some Q devices
- -**October 25, 2019 to November 1, 2019 Business Edition Code Updates** - -230、Fix cloning Google Play download of 64-bit APP
-229、Fix Enterprise WeChat
-228、Fix Telegram
- -**October 8, 2019 to October 24, 2019 Business Edition Code Updates** - -227、Fix the exception of AppOspManager under Android P
-226、Add the missing Hook of ActivityTaskManager under Android P
-225、Fix the exception of Activity Top Resume under Android P
-224、Support running in system multi-user mode
- -**October 8, 2019 Business Edition Code Updates** - -223、Fix the issue of Android P or above internal app returning to desktop exception
-222、64-bit branch support for Android Q
- -**September 20, 2019 to October 7, 2019 Business Edition Code Updates** - -221、Fix the problem that the apk installed in the extension plugin cannot display the icon and name correctly
-220、Fix the problem that twitter cannot be opened
-219、Officially compatible with Android Q official version
-218、Fix the problem that some Activity of Android Q cannot be opened again
-217、Initially compatible with Android Q official version
-216、Fix several bugs of 64-bit branch
-215、Newly add 64-bit branch to support 32-bit plugins, the branch supports 32-bit old devices and 64-bit devices can support 32-bit old applications in the case of 32-bit plug-ins
- -**December 2017 to July 30, 2019 Business Edition Code Updates** - -214、Improve APP layer prompt message
-213、Improve some code
-212、Fix the method of sending broadcast from host to plug-in
-211、Compatible with the latest gradle plug-in
-210、Add broadcast namespace to avoid multiple APPs that use VA technology to interfere with each other
-209、Fix the problem that IMO can't be opened
-208、Fix the problem that some ContentProvider cannot be found
-207、Support pure 32-bit mode to be compatible with old devices
-206、Preliminary support for pure 64-bit mode to cope with the change of Google Marketplace strategy in August
-205、Adapt to Android Q beta4
-204、Fix the problem that Cargo LaLa can't be installed
-203、Optimize the decision logic of 64-bit apk
-202、Fix networking of App with network certificate configuration
-201、Refactored component state management
-200、Optimize MIUI/EMUI ContentProvider compatibility
-199、Fix StorageStats Hook
-198、Fix Kwai can't login
-197、Fix YY can not start, better compatibility with plug-in framework
-196、Fix Facebook login
-195、Fix the problem of Google Play downloaded App can not find so (Royal War)
-194、Fix split apk support
-193、Fix Youtube can not start
-192、Fix the problem that Youku can not start
-191、Fix the bug that there may be broadcast namespace conflict between apps when multi space
-190、Adopt a new strategy to bypass the Hidden Policy API after Android P
-189、Adapted to Android Q(beta1)
-188、Fix the problem that some APPs of Huawei devices cannot recognize the storage
-187、Fix the problem that the startup process may fail dues to the APP cannot run
-186、Fix the problem that some native symbols cannot be found in 4.4 devices
-185、Fix the problem that some devices fail to get the package name of WebView
-184、Fix the problem of Service detail processing
-183、Optimize startup speed
-182、Fix WebView loading failure in a few devices
-181、Fix the problem of Lib decision
-180、 Fix the problem that some Huawei models cannot read the sdcard
-179、Fix the problem that Service may exist
-178、Allow to determine whether Activity is started externally based on intent
-177、Fix Gms and Google Play launching to incorrect environment on some models
-176、Fix the compatibility problem caused by the newly implemented StaticBroadcast
-175、Fix the problem that apache.http.legacy cannot be used on Android P
-174、Implementation of Native trace
-173、Optimize IO Redirect performance
-172、Fix the problem that wechat can't connect to the network in some cases
-171、Fix the small probability process attach of incorrect BUG
-170、Start the next phase of ROADMAP
-169、Fix the problem caused by the inability of Android P to register more than 1000 broadcasts
-168、Fix the DeadLock that may cause ANR
-167、Fix the problem that some apps fail to load so dynamically
-166、Fix the problem that some models have black screen when opened for the first time under the without installation running environment
-165、Compatible with many mainstream Android emulators
-164、Optimize startup performance
-163、Solve several memory leaks
-162、Fix the problem of IO Redirect priority
-161、Fix the problem of no network connection of Messenger for devices below 8.0
-160、Fix the bug that the internal app is still retained when the external APP is uninstalled when double space
-159、Fix the problem that some Tencent reinforcement cannot run
-158、 Fix the bug that Instagram cannot login to Facebook
-157、Fix the bug that the process may start repeatedly with small probability
-156、Fix the bug that GET_PERMISSIONS does not get permission
-155、Fix the bug that startActivityIntentSender
-154、Fix the problem that some Activity cannot be started in Vivo devices
-153、Fix the problem that app cannot call external APP to select files
-152、Improve the compatibility of Android P
-151、Compatible with Google service of Android P
-150、Fix the problem that some functions of Messenger are abnormal
-149、Improve IO Redirect
-148、Adapt a lot of Gms, fix the problem that the process restarts infinitely during the operation of Gms
-147、Realize the running mechanism of Service
-146、Improve 64bit, provide some ROM configuration 64bit Engine permission API
-145、Fix the Activity startup problem on 4.4 devices
-144、Support excludeFromRecent property
-143、Fix the problem that Instagram can't Facebook login
-142、Fix the problem of Facebook first login flashback
-141、Support to run Gms, Google play, Play game in 64-bit mode
-140、Support downloading and installing APPs in Google play running without installation/in multi space
-139、Fix the bug of DownloadManagerG
-138、Fix the bug of restarting the interface when Google play returns to the upper level
-137、Fix the problem of so decision in without installation mode
-136、Optimize the build script to facilitate the introduction of the project
-135、Fix the problem that mobile MM SDK can't start
-134、Fix the bug of WeChat Shake
-133、Fix the bug of ZTE device instability
-132、Support IO Redirect under ARM64
-131、Fix the bug that the internal app is not updated when the external app is updated in USE_OUTSIDE mode
-130、Compatible with the latest Android 9.0 (code name: pie) and the four Preview versions released before the official version
-129、Compatible with x86 devices with built-in houdini
-128、WindowPreview technology, so that the app launch and the real app to achieve the same speed
-127、New ActivityStack to improve the quality of APP running
-126、Solve the problem of app running exception with adding Atlas Framework
-125、Now you can define the specific behavior of the virtual app back to the desktop
-124、APP in the double space dynamically updated with the system, no need to manually check
-123、Support targetSdkVersion >= 26, but still can normally run the low version of the APP
-122、Compatible with QDroid virtual engine of Tencent Game Manager (beta)
-121、Extensive refactoring of the underlying code to greatly improve the running speed
-120、Fix the problem that NetEase News cannot be cancelled after sharing to Weibo
-119、Fix the problem that APP custom permission cannot be identified
-118、Fix the problem that the MoJi weatherAPP can not start
-117、Fix the problem that some government APPs cannot be started
-116、See code for details of API changes
-115、Fix the problem of Samsung series APPs calling each other
-114、Fix the account problem of Xiaomi APP in non-Xiaomi system
-113、Fix third-party calls such as share/send, the return page is not normal
-112、Fix the problem of APP Store of QQ can not be installed
-111、Call the third-party APP, encryption of uri
-110、Adapt the front bangs
-109、Adapt the hook of Xiaomi rom
-108、Adapt Nubia recording problem
-107、 Internal hover window permission control
-106、Optimize the processing of custom notification bar
-105、Fix the INCLUDE_CODE permission problem of Context
-104、Adapt Huawei, oppo's corner mark
-103、Fix the process restart problem of Baidu video
-102、Fix some snapchat can not start problem
-101、Adapt autofill service, such as piexl series
-100、Improve the 64-bit io hook
-99、Optimize the compatibility of hook library, add back dlopen
-98、Move the 64-bit extension package so to the 32-bit main package. (After jni code change, please build once before Run)
-97、Notification bar changes: adapt 8.1 notification channel; remove the application, remove all notifications of the application
-96、Compatible with some APPs, need to set android:largeHeap=true
-95、Fix the ffmpeg library video can not play the problem
-94、Optimize horizontal and vertical screen switching
-93、Lower the limitation of calling external Activity through Intent
-92、Compatible with MG SDK
-91、64-bit support is still in the development stage
-90、Update obfuscation configuration APP/proguard-rules.pro, must add the rule -dontshrink
-89、Optimize the mock device, for example: after mock, some APPs do not appear device verification
-88、Improve dex2oat compatibility
-87、Optimize mock positioning
-86、Remove dlopen
-85、targetVersion can be changed to 26: support targetVersion<23 app dynamic permission application, support targetVersion<24 file Uri
-84、installPackage changed to default asynchronous form
-83、In order to support 64-bit mode, change back to aidl
-82、Remove SettingHandler can now dynamically set special rules, the rules will be stored, no need to repeat settings
-81、Add 2 native_setup
-80、Improve jobService compatibility
-79、ShortcutService related: associated VASettings.ENABLE_INNER_SHORTCUT
-78、For the sake of stability and running efficiency, remove the Bluetooth, wifi and undeclared permission adaptations of the previous version
-77、Add APP starts abnormal broadcast Constants.ACTION_PROCESS_ERROR
-76、Fix a few games horizontal screen judgment problem
-75、Demo adds device mock
-74、Adapt Vivo a custom permission (background pop-up), VA is to return a history acitivty to the foreground. Vivo needs this permission
-73、If there is no Bluetooth permission, return to the default value (overseas use it)
-72、Fix uid permission check problem
-71、Security updates, file permission control for internal applications
-70、Improve the compatibility of internal APP calls, third-party login, sharing
-69、Automatic filtering of external ContentProvider without permissions
-68、Add feature: internal APP permission check (closed by default)
-67、Device mock: Build class and build.prop
-66、Improve the compatibility of the APP progard
-65、Adapt to Samsung wifimanager
-64、Fix ipc framework a parameter passing problem (IPCMethod this class must be updated)
-63、Fill the 7.0 notification bar hook
-62、Fix 8.0 dynamic shortcut menu hook
-61、SettingHandler adds a new adaptation interface, mainly adapted to a variety of games
-60、Functional changes: google automatic installation to manual installation, to avoid the first start time too long
-59、Prohibit access to an external ContentProvider
-58、Adapt Huawei desktop icon number
-57、Permission classification notes, mark the permissions that can be deleted
-56、Add a switch for the APP in double space mode to follow external upgrade
-55、Improve the APP jni compatibility
-54、Improve compatibility with APP integration of other plug-in frameworks
-53、Add setting interface to set according to package name
-52、Increase the scope of Uri adaptation to support sharing and viewing files via Uri
-51、Fix a problem in Samsung 8.0
-50、Improve the compatibility of the app components that come with the system, better compatibility with chrome webview, google service.
-49、Improve the stability of ART
-48、Increase camera adaptation range
-47、Support internal App shortcut management under 8.0
-46、Fix exec exception
-45、Improve stability (Fix WeChat login flashback)
-44、Fix the WeChat database crash problem
-43、Fix the crash problem of some 4.4 devices
-42、Fix the background application easy to be killed, Tudou video black screen, Sina Weibo can not open, Youku twice return can not exit
-41、Increase the application keepalive mechanism, APP double space is less likely to be killed
-40、Optimize the performance of virtual engine startup
-39、Compatible with most of the reinforcement, third-party APP compatibility compared to the previous version to improve 40% +
-38、Fix the shortcut icon is incorrect under some roms
-37、Compatible with previous component StubFileProvider
-36、Adapt the virtual IMEI of some new roms
-35、Improve process initialization code to increase stability
-34、Add internal send Intent.ACTION_BOOT_COMPLETED broadcast, you can set the switch
-33、Adapt the associated google play game, support the game using google login
-32、Adapt the google service framework for android O
-31、Adapt android O shortcut
-30、Adapt to headset mode
-29、Some roms on the size of the intent limit, demo add scaling shortcut icon code
-28、Fix the bug in the case of multi space
-27、Fix the bug of MediaController in some cases
-26、Fix the error of StubFileProvider in 4.1.2
-25、Share uri processing
-24、Fix the callbacks of cross-app calls to Activity
-23、Block switch of notification bar of foreground service
-22、Companying doc
-21、Improve the CHOOSE callback of intent inside VA
-20、Android O notification bar adaptation 2
-19、 ipc framework optimization, improve the accuracy of determining the survival of the binder
-18、jni's log switch Android.mk:LOCAL_CFLAGS += -DLOG_ENABLE
-17、Confusion configuration
-16、Notification bar adaptation of Android O
-15、Fix the problem of network lag in some APPs
-14、Adaptation of android 8.0 dl_open (jni loading)
-13、Fix the bug of Huawei emui8.0
-12、Improve positioning
-11、Set the phone information, imei disguise algorithm
-10、Adapted to 8.0 a certain function (the main APP: whatsAPP)
-9、Fix internal WeChat and other applications, can not update the picture, video
-8、Demo add the installation of listening, automatically upgrade the clone mode applications
-7、Adaptations of 7.0 file provider adaptations
-6、Add positioning code
-5、The code is optimized for the architecture
-4、Different features from the open source version
-3、Solve some problems of WeChat being blocked
-2、Repaire some devices compatibility
-1、Repaire 12 small bugs
-
From dce9e1b1bcef64fdb90d7fa96e5ba3e1a293b4ec Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 23 Oct 2023 15:17:49 +0800 Subject: [PATCH 260/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c660eb805..005b638ff 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ VA开发文档请参考:[开发文档](doc/VADev.md) 授权说明 ------ -VirtualApp虚拟机技术归属于:济宁市罗盒网络科技有限公司,于2015年至2021年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` +VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原:济宁市罗盒网络科技有限公司),于2015年至2023年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
负责人:张总
From b124823b2d83853c693c0f1ad4c8dc49a3a78481 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 23 Oct 2023 15:39:15 +0800 Subject: [PATCH 261/334] Update README.md --- README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 005b638ff..52f5001b1 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,17 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2023年商业版代码更新详细 ------ +**2023年10月8号 至 2023年 10月23号 商业版代码更新内容** + +478、修复Annotation依赖包为空的问题
+477、修复抖音等APP由于动态框架导致无法打开Activity的问题
+476、修复纯Java APP在64位下以32位模式安装的问题
+475、修复了13.0+上的class linker偏移检测问题
+474、调整默认使用isUseRealDataDir模拟真实路径
+473、JobServiceStub适配
+472、IO重定向增加对renameat2的hook
+471、修复APK安装模式下某些APP拍照黑屏
+470、修复APK安装模式下微信小程序无法使用的问题
**2023年9月16号 至 2023年 10月7号 商业版代码更新内容** @@ -263,14 +274,15 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 465、修复WhatsApp等部分APP启动后界面白屏问题
464、适配Alarms 相关API +
+2017年 12月 至 2023年 9 月 15 日 商业版代码更新内容(下拉打开)
+ **2023年9月6号 至 2023年 9月15号 商业版代码更新内容** 463、14.0上JobScheduler API适配
462、修复从sdcard上安装时signature可能获取的可能不是最旧的问题
461、LocaleManager适配
-
-2017年 12月 至 2023年 8 月 5 日 商业版代码更新内容(下拉打开)
**2023年8月16号 至 2023年 9月5号 商业版代码更新内容** From cb62b85bb9b678b683a76190b3d5ee80b1461e97 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 21 Nov 2023 09:35:05 +0800 Subject: [PATCH 262/334] Update README.md --- README.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 52f5001b1..828aa7e96 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,24 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2023年商业版代码更新详细 ------ +**2023年10月24号 至 2023年 11月22号 商业版代码更新内容** + +490、取消对Xposed依赖
+489、适配最新版微信
+488、适配setCompatibilityVersion
+487、取消hookGetCallingUid对xposed的依赖
+486、蓝牙适配
+485、AddToDisplayAsUser处理
+478、PendingIntent适配
+484、MediaRecorder适配
+483、处理dispatchVolumeKeyEvent API
+482、修复AttributionSource cast crash
+481、增加配置:是否优先使用外部app
+480、修复启动前台service crash
+479、修复14.0上renameat太短导致hook后覆盖其他函数的问题
+ + + **2023年10月8号 至 2023年 10月23号 商业版代码更新内容** 478、修复Annotation依赖包为空的问题
@@ -265,6 +283,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 471、修复APK安装模式下某些APP拍照黑屏
470、修复APK安装模式下微信小程序无法使用的问题
+
+2017年 12月 至 2023年 10 月 7 日 商业版代码更新内容(下拉打开)
+ **2023年9月16号 至 2023年 10月7号 商业版代码更新内容** 469、移除已经废弃的虚拟定位代码
@@ -274,8 +295,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 465、修复WhatsApp等部分APP启动后界面白屏问题
464、适配Alarms 相关API -
-2017年 12月 至 2023年 9 月 15 日 商业版代码更新内容(下拉打开)
**2023年9月6号 至 2023年 9月15号 商业版代码更新内容** From 6a1a8a54f709fa2e70d5dd8ef8689967aa449df3 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sun, 3 Dec 2023 23:33:06 +0800 Subject: [PATCH 263/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 828aa7e96..c9dd92348 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2023年商业版代码更新详细 ------ -**2023年10月24号 至 2023年 11月22号 商业版代码更新内容** +**2023年10月24号 至 2023年 12月4号 商业版代码更新内容** 490、取消对Xposed依赖
489、适配最新版微信
From 942e503242e187fcb08b74ba607784de625e083a Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 19 Dec 2023 15:01:59 +0800 Subject: [PATCH 264/334] Update README.md --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c9dd92348..99119245c 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2023年商业版代码更新详细 ------ +**2023年12月5号 至 2023年 12月20号 商业版代码更新内容** + +491、修复储存空间异常的问题
+ + **2023年10月24号 至 2023年 12月4号 商业版代码更新内容** 490、取消对Xposed依赖
@@ -269,7 +274,8 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 480、修复启动前台service crash
479、修复14.0上renameat太短导致hook后覆盖其他函数的问题
- +
+2017年 12月 至 2023年 10 月 23 日 商业版代码更新内容(下拉打开)
**2023年10月8号 至 2023年 10月23号 商业版代码更新内容** @@ -283,8 +289,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 471、修复APK安装模式下某些APP拍照黑屏
470、修复APK安装模式下微信小程序无法使用的问题
-
-2017年 12月 至 2023年 10 月 7 日 商业版代码更新内容(下拉打开)
**2023年9月16号 至 2023年 10月7号 商业版代码更新内容** From d50721bd17ce3d90c222c910bf57e44433f90f95 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 3 Jan 2024 17:40:17 +0800 Subject: [PATCH 265/334] Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99119245c..03dbeb57b 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ VA开发文档请参考:[开发文档](doc/VADev.md) 授权说明 ------ -VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原:济宁市罗盒网络科技有限公司),于2015年至2023年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` +VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原:济宁市罗盒网络科技有限公司),于2015年至2024年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
负责人:张总
@@ -250,9 +250,13 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原
-2017年-2023年商业版代码更新详细 +2017年-2024年商业版代码更新详细 ------ +**2023年12月21号 至 2024年 1月4号 商业版代码更新内容** + +492、适配libc可能没有R权限的情况
+ **2023年12月5号 至 2023年 12月20号 商业版代码更新内容** 491、修复储存空间异常的问题
From 6c9183481b28e24d424015a1abf384465ebfef08 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 24 Jan 2024 09:21:19 +0800 Subject: [PATCH 266/334] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 03dbeb57b..151d1425c 100644 --- a/README.md +++ b/README.md @@ -253,10 +253,18 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2023年1月5号 至 2024年 1月24号 商业版代码更新内容** + +493、适配最新版微信
+ **2023年12月21号 至 2024年 1月4号 商业版代码更新内容** 492、适配libc可能没有R权限的情况
+ +
+2017年 12月 至 2023年 12 月 20 日 商业版代码更新内容(下拉打开)
+ **2023年12月5号 至 2023年 12月20号 商业版代码更新内容** 491、修复储存空间异常的问题
@@ -278,8 +286,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 480、修复启动前台service crash
479、修复14.0上renameat太短导致hook后覆盖其他函数的问题
-
-2017年 12月 至 2023年 10 月 23 日 商业版代码更新内容(下拉打开)
**2023年10月8号 至 2023年 10月23号 商业版代码更新内容** From bdac2eeac189b6f90702f38f34bc7db5d50a2b41 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 24 Jan 2024 09:24:59 +0800 Subject: [PATCH 267/334] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 151d1425c..604810af6 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2023年1月5号 至 2024年 1月24号 商业版代码更新内容** +494、Activity Token获取适配
493、适配最新版微信
**2023年12月21号 至 2024年 1月4号 商业版代码更新内容** From f695dc66202eb3fd8558d229a48c5569f1c63f5a Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sun, 18 Feb 2024 11:22:56 +0800 Subject: [PATCH 268/334] Update README.md --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 604810af6..e4be0d0dd 100644 --- a/README.md +++ b/README.md @@ -253,19 +253,32 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2023年1月25号 至 2024年 2月18号 商业版代码更新内容** + +504、修复抖音在部分手机无法打开的问题
+503、修复抖音在部分手机运行一小段时间后崩溃的问题
+502、修复抖音在部分手机crash后一直打不开的问题
+501、修复抖音极速版在部分手机无法打开的问题
+500、修复抖音极速版在部分手机运行一小段时间后崩溃的问题
+499、修复抖音极速版在部分手机crash后一直打不开的问题
+498、UserManager相关API适配
+497、PackageManager相关API适配
+496、Notification相关API适配
+495、FingerprintManager相关API适配
+ **2023年1月5号 至 2024年 1月24号 商业版代码更新内容** 494、Activity Token获取适配
493、适配最新版微信
+
+2017年 12月 至 2024年 1 月 4 日 商业版代码更新内容(下拉打开)
+ **2023年12月21号 至 2024年 1月4号 商业版代码更新内容** 492、适配libc可能没有R权限的情况
-
-2017年 12月 至 2023年 12 月 20 日 商业版代码更新内容(下拉打开)
- **2023年12月5号 至 2023年 12月20号 商业版代码更新内容** 491、修复储存空间异常的问题
From 776b07c463c5e9652814d0858b7367a9cc37d6a3 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sun, 18 Feb 2024 11:23:48 +0800 Subject: [PATCH 269/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e4be0d0dd..4710a9c73 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ -**2023年1月25号 至 2024年 2月18号 商业版代码更新内容** +**2024年1月25号 至 2024年 2月18号 商业版代码更新内容** 504、修复抖音在部分手机无法打开的问题
503、修复抖音在部分手机运行一小段时间后崩溃的问题
@@ -266,7 +266,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 496、Notification相关API适配
495、FingerprintManager相关API适配
-**2023年1月5号 至 2024年 1月24号 商业版代码更新内容** +**2024年1月5号 至 2024年 1月24号 商业版代码更新内容** 494、Activity Token获取适配
493、适配最新版微信
From dfc8e935f6280a36e3e45bf4d50c4d9c3f84f713 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 6 Mar 2024 15:07:11 +0800 Subject: [PATCH 270/334] Update README.md --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4710a9c73..396530ccc 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,15 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年2月19号 至 2024年 3月6号 商业版代码更新内容** + +509、修通知跳转Crash
+508、AMS API适配
+507、DevicePolicyManager API适配
+506、BlueTooth API适配
+505、修复抖音crash问题
+ + **2024年1月25号 至 2024年 2月18号 商业版代码更新内容** 504、修复抖音在部分手机无法打开的问题
@@ -266,14 +275,16 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 496、Notification相关API适配
495、FingerprintManager相关API适配
+ +
+2017年 12月 至 2024年 1 月 24 日 商业版代码更新内容(下拉打开)
+ + **2024年1月5号 至 2024年 1月24号 商业版代码更新内容** 494、Activity Token获取适配
493、适配最新版微信
-
-2017年 12月 至 2024年 1 月 4 日 商业版代码更新内容(下拉打开)
- **2023年12月21号 至 2024年 1月4号 商业版代码更新内容** 492、适配libc可能没有R权限的情况
From 676fb1859bbf6b63fa97145f8961cdd4fbbc20e6 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 1 Apr 2024 09:34:11 +0800 Subject: [PATCH 271/334] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 396530ccc..2a523c131 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年3月7号 至 2024年 4月2号 商业版代码更新内容** + +510、修复数款游因为戏二次注册provider导致无法打开
+ + **2024年2月19号 至 2024年 3月6号 商业版代码更新内容** 509、修通知跳转Crash
From 8b26af82872b034240da2718fd27bf5ec57e210e Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 19 Apr 2024 11:42:15 +0800 Subject: [PATCH 272/334] Update README.md --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2a523c131..c8e296e2b 100644 --- a/README.md +++ b/README.md @@ -253,11 +253,21 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年4月4号 至 2024年 4月19号 商业版代码更新内容** + +513、修复link&unlink参数没有处理重定向的问题
+512、修复AutoFillManagerStub未生效问题
+511、适配高版本ShadowJobService
+ **2024年3月7号 至 2024年 4月2号 商业版代码更新内容** 510、修复数款游因为戏二次注册provider导致无法打开
+
+2017年 12月 至 2024年 3 月 5 日 商业版代码更新内容(下拉打开)
+ + **2024年2月19号 至 2024年 3月6号 商业版代码更新内容** 509、修通知跳转Crash
@@ -281,10 +291,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 495、FingerprintManager相关API适配
-
-2017年 12月 至 2024年 1 月 24 日 商业版代码更新内容(下拉打开)
- - **2024年1月5号 至 2024年 1月24号 商业版代码更新内容** 494、Activity Token获取适配
From a08533f1a66b9f08c797a028134785fd6c084cb6 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 7 May 2024 09:43:53 +0800 Subject: [PATCH 273/334] Update README.md --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c8e296e2b..8d4c51950 100644 --- a/README.md +++ b/README.md @@ -253,20 +253,27 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年4月20号 至 2024年 5月7号 商业版代码更新内容** + +516、适配华为账户登录和授权登录等功能
+515、适配荣耀账户登录和授权登录等功能
+514、修改Service中getApplicationContext返回Null的问题
+ + **2024年4月4号 至 2024年 4月19号 商业版代码更新内容** 513、修复link&unlink参数没有处理重定向的问题
512、修复AutoFillManagerStub未生效问题
511、适配高版本ShadowJobService
+
+2017年 12月 至 2024年 4 月 2 日 商业版代码更新内容(下拉打开)
+ **2024年3月7号 至 2024年 4月2号 商业版代码更新内容** 510、修复数款游因为戏二次注册provider导致无法打开
-
-2017年 12月 至 2024年 3 月 5 日 商业版代码更新内容(下拉打开)
- **2024年2月19号 至 2024年 3月6号 商业版代码更新内容** From 4cf99ee28f3de5197217dd94fcdc5b5944dfb142 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 7 May 2024 09:44:36 +0800 Subject: [PATCH 274/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d4c51950..6f1c186d9 100644 --- a/README.md +++ b/README.md @@ -257,7 +257,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 516、适配华为账户登录和授权登录等功能
515、适配荣耀账户登录和授权登录等功能
-514、修改Service中getApplicationContext返回Null的问题
+514、修复Service中getApplicationContext返回Null的问题
**2024年4月4号 至 2024年 4月19号 商业版代码更新内容** From 7a1fd174c8dc43e0e2bcc2e54c2847c06432c35a Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 3 Jun 2024 13:41:13 +0800 Subject: [PATCH 275/334] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 6f1c186d9..3fc90093b 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年5月8号 至 2024年 6月3号 商业版代码更新内容** + +518、修复微信在鸿蒙4.0+上无法使用的问题
+517、调整VA demo package name
+ **2024年4月20号 至 2024年 5月7号 商业版代码更新内容** 516、适配华为账户登录和授权登录等功能
From e9bcf4ca14e413cdce288b2753f5e4400a577880 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 15 Jun 2024 09:45:56 +0800 Subject: [PATCH 276/334] Update README.md --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3fc90093b..27d7af9ee 100644 --- a/README.md +++ b/README.md @@ -253,11 +253,20 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年6月4号 至 2024年 6月16号 商业版代码更新内容** + +518、将内置的Java hook框架SandHook调整为可选配置
+517、修复VA_ENABLE_EXT_FULL_SOURCE_CODE功能选项开启时,加载so错误的问题
+ + **2024年5月8号 至 2024年 6月3号 商业版代码更新内容** 518、修复微信在鸿蒙4.0+上无法使用的问题
517、调整VA demo package name
+
+2017年 12月 至 2024年 5 月 7 日 商业版代码更新内容(下拉打开)
+ **2024年4月20号 至 2024年 5月7号 商业版代码更新内容** 516、适配华为账户登录和授权登录等功能
@@ -271,8 +280,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 512、修复AutoFillManagerStub未生效问题
511、适配高版本ShadowJobService
-
-2017年 12月 至 2024年 4 月 2 日 商业版代码更新内容(下拉打开)
**2024年3月7号 至 2024年 4月2号 商业版代码更新内容** From 859a2cb3217a21eb8838820e5e33e8d290d5c92a Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 15 Jun 2024 09:46:27 +0800 Subject: [PATCH 277/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 27d7af9ee..bc0661812 100644 --- a/README.md +++ b/README.md @@ -255,8 +255,8 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2024年6月4号 至 2024年 6月16号 商业版代码更新内容** -518、将内置的Java hook框架SandHook调整为可选配置
-517、修复VA_ENABLE_EXT_FULL_SOURCE_CODE功能选项开启时,加载so错误的问题
+520、将内置的Java hook框架SandHook调整为可选配置
+519、修复VA_ENABLE_EXT_FULL_SOURCE_CODE功能选项开启时,加载so错误的问题
**2024年5月8号 至 2024年 6月3号 商业版代码更新内容** From 3b11fa72b13883c9a07b4e6422677ffcf6b37917 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 1 Jul 2024 09:24:06 +0800 Subject: [PATCH 278/334] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bc0661812..dc72d46cd 100644 --- a/README.md +++ b/README.md @@ -253,19 +253,25 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年6月17号 至 2024年 7月2号 商业版代码更新内容** + +522、AttributionSoure中的uid调整
+521、修复微信注册,找回账号等几个界面白屏的问题
+ **2024年6月4号 至 2024年 6月16号 商业版代码更新内容** 520、将内置的Java hook框架SandHook调整为可选配置
519、修复VA_ENABLE_EXT_FULL_SOURCE_CODE功能选项开启时,加载so错误的问题
+
+2017年 12月 至 2024年 6 月 23 日 商业版代码更新内容(下拉打开)
**2024年5月8号 至 2024年 6月3号 商业版代码更新内容** 518、修复微信在鸿蒙4.0+上无法使用的问题
517、调整VA demo package name
-
-2017年 12月 至 2024年 5 月 7 日 商业版代码更新内容(下拉打开)
+ **2024年4月20号 至 2024年 5月7号 商业版代码更新内容** From 268e158eecb4cefa44d523b30dd6a5e94da93533 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 17 Jul 2024 14:06:16 +0800 Subject: [PATCH 279/334] Update README.md --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc72d46cd..5cb3a7d54 100644 --- a/README.md +++ b/README.md @@ -253,18 +253,27 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年7月3号 至 2024年 7月18号 商业版代码更新内容** + +526、对数个地方的几十个API进行了适配,提升了稳定性
+525、调整stopService不再走initProcess流程
+524、修复 startprocess启动App后再次进入VActivityManagerService导致死锁的问题
+523、修复锁屏/亮屏广播引起的crash问题
+ + **2024年6月17号 至 2024年 7月2号 商业版代码更新内容** 522、AttributionSoure中的uid调整
521、修复微信注册,找回账号等几个界面白屏的问题
+
+2017年 12月 至 2024年 6 月 16 日 商业版代码更新内容(下拉打开)
+ **2024年6月4号 至 2024年 6月16号 商业版代码更新内容** 520、将内置的Java hook框架SandHook调整为可选配置
519、修复VA_ENABLE_EXT_FULL_SOURCE_CODE功能选项开启时,加载so错误的问题
-
-2017年 12月 至 2024年 6 月 23 日 商业版代码更新内容(下拉打开)
**2024年5月8号 至 2024年 6月3号 商业版代码更新内容** From 06f32e1fc97fed2042080a92b6a2fbfabfa6fe97 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 2 Aug 2024 13:58:06 +0800 Subject: [PATCH 280/334] Update README.md --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5cb3a7d54..9e0f2e587 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,22 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年7月19号 至 2024年 8月2号 商业版代码更新内容** + +538、修复sandhook崩溃问题
+537、修复sandhook hook不起效问题
+536、替换sandhook中inline hook部分
+535、修复android.permission.DETECT_SCREEN_CAPTURE权限导致的crash问题
+534、修复静态广播导致的crash问题
+533、修复百度搜索crash的问题
+532、修复ResolveActivity跳转到外部应用时没有过滤export为false的场景导致crash
+531、修复在某些华为设备上微信白屏的问题
+530、修复微信流量异常的问题
+529、class_linker适配android 15
+528、修复 readlinkat参数问题导致的crash
+527、解决某些unity路径检测的问题
+ + **2024年7月3号 至 2024年 7月18号 商业版代码更新内容** 526、对数个地方的几十个API进行了适配,提升了稳定性
@@ -260,14 +276,14 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 524、修复 startprocess启动App后再次进入VActivityManagerService导致死锁的问题
523、修复锁屏/亮屏广播引起的crash问题
+
+2017年 12月 至 2024年 7 月 2 日 商业版代码更新内容(下拉打开)
**2024年6月17号 至 2024年 7月2号 商业版代码更新内容** 522、AttributionSoure中的uid调整
521、修复微信注册,找回账号等几个界面白屏的问题
-
-2017年 12月 至 2024年 6 月 16 日 商业版代码更新内容(下拉打开)
**2024年6月4号 至 2024年 6月16号 商业版代码更新内容** From a93a5230155be18425d9fd619e3312503aedd337 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 8 Aug 2024 09:30:24 +0800 Subject: [PATCH 281/334] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9e0f2e587..74d3662c8 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,10 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年8月3号 至 2024年 8月8号 商业版代码更新内容** + +538、修复微信等APP因为webview导致的crash问题
+ **2024年7月19号 至 2024年 8月2号 商业版代码更新内容** 538、修复sandhook崩溃问题
From ffa378016848f5cc26b9da6daed6c28063a72fcf Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 8 Aug 2024 09:31:57 +0800 Subject: [PATCH 282/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 74d3662c8..799f5d659 100644 --- a/README.md +++ b/README.md @@ -275,8 +275,8 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2024年7月3号 至 2024年 7月18号 商业版代码更新内容** -526、对数个地方的几十个API进行了适配,提升了稳定性
-525、调整stopService不再走initProcess流程
+526、适配了几十个API,很大程度提升了稳定性
+525、调整stopService不再走initProcess流程,解决了某些情况下的死锁问题
524、修复 startprocess启动App后再次进入VActivityManagerService导致死锁的问题
523、修复锁屏/亮屏广播引起的crash问题
From ea3aa86e0079519b458714777f862c80e1c3b3b2 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 8 Aug 2024 14:11:50 +0800 Subject: [PATCH 283/334] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 799f5d659..72d0e928b 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ VA的其他特性 进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 - 全版本支持
-支持5.0-14.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 +支持5.0-15.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 - 易扩展与集成
VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 @@ -182,6 +182,7 @@ VA已被**上百家**企业进行了广泛测试,包含**数十家上市公司 12.0 | 支持 13.0 | 支持 14.0 | 支持 +15.0 | 支持
@@ -237,7 +238,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 商业版主要更新 ------ -1. 兼容最新Android 14.0 +1. 兼容最新Android 15.0 2. 不易被杀毒软件误报 3. 框架优化,性能大幅提升 4. 手机系统及APP兼容性大幅提升 From e46fcc5c63e476d1840542492a72d670096a440e Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 8 Aug 2024 14:12:23 +0800 Subject: [PATCH 284/334] Update README_eng.md --- README_eng.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README_eng.md b/README_eng.md index 89ffdb081..fbb73c8fe 100644 --- a/README_eng.md +++ b/README_eng.md @@ -131,7 +131,7 @@ VA Other features Process-level "virtual machine", VA's unique implementation model makes its performance almost the same as that of the native APP, and does not need a long startup of ordinary virtual machines. - Full version support
-Support 5.0-14.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. +Support 5.0-15.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. - Easy Expansion and Integration
The integration of VA is similar to the normal Android library, even if your APP has been online, you can conveniently integrate VA and enjoy the capability brought by VA. @@ -177,7 +177,7 @@ System version | Whether to support 11.0 | support 12.0 | support 13.0 | support -14.0 | support +15.0 | support
@@ -232,7 +232,7 @@ If you use VirtualApp for **internal use, business profit or upload it to the ap Major updates of the business version ------ -1. Support Android 14.0 +1. Support Android 15.0 2. Not easily misreported by anti-virus software 3. Framework optimization, performance greatly improved 4. Mobile system and APP compatibility greatly improved From 291099fc1a47044754d933d57d9158289f8a4cde Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 21 Aug 2024 16:44:22 +0800 Subject: [PATCH 285/334] Update README.md --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 72d0e928b..7337ef888 100644 --- a/README.md +++ b/README.md @@ -254,9 +254,17 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年8月9号 至 2024年 8月22号 商业版代码更新内容** + +544、修复Native的一个空指针问题
+543、修复Native的某个函数由于栈上随机数导致判断出错
+542、修复unity中的检测问题
+541、修复publishService crash问题
+540、修复getPid死循环崩溃问题
+ **2024年8月3号 至 2024年 8月8号 商业版代码更新内容** -538、修复微信等APP因为webview导致的crash问题
+539、修复微信等APP因为webview导致的crash问题
**2024年7月19号 至 2024年 8月2号 商业版代码更新内容** @@ -273,6 +281,8 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 528、修复 readlinkat参数问题导致的crash
527、解决某些unity路径检测的问题
+
+2017年 12月 至 2024年 7 月 18 日 商业版代码更新内容(下拉打开)
**2024年7月3号 至 2024年 7月18号 商业版代码更新内容** @@ -281,8 +291,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 524、修复 startprocess启动App后再次进入VActivityManagerService导致死锁的问题
523、修复锁屏/亮屏广播引起的crash问题
-
-2017年 12月 至 2024年 7 月 2 日 商业版代码更新内容(下拉打开)
**2024年6月17号 至 2024年 7月2号 商业版代码更新内容** From 068974cae3737ad71314396b56fd9f073048504a Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 3 Sep 2024 14:27:50 +0800 Subject: [PATCH 286/334] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7337ef888..4c32cb990 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,10 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年8月23号 至 2024年 9月4号 商业版代码更新内容** + +544、修复IO重定向中一系列函数未对dfd正确处理
+ **2024年8月9号 至 2024年 8月22号 商业版代码更新内容** 544、修复Native的一个空指针问题
From c22fc886a09770867c8059351cd0ae275fb695fc Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 3 Sep 2024 14:28:16 +0800 Subject: [PATCH 287/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c32cb990..d8b61b3a6 100644 --- a/README.md +++ b/README.md @@ -256,7 +256,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2024年8月23号 至 2024年 9月4号 商业版代码更新内容** -544、修复IO重定向中一系列函数未对dfd正确处理
+545、修复IO重定向中一系列函数未对dfd正确处理
**2024年8月9号 至 2024年 8月22号 商业版代码更新内容** From 58d73c5d9547ee765f508bdb7d4508d0f91dd556 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 14 Sep 2024 13:59:09 +0800 Subject: [PATCH 288/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d8b61b3a6..1ba6d6e64 100644 --- a/README.md +++ b/README.md @@ -254,7 +254,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ -**2024年8月23号 至 2024年 9月4号 商业版代码更新内容** +**2024年8月23号 至 2024年 9月14号 商业版代码更新内容** 545、修复IO重定向中一系列函数未对dfd正确处理
From 3bd6dcc2f8e646d530a3ef3c0d031a42c34abc94 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 12 Oct 2024 17:18:38 +0800 Subject: [PATCH 289/334] Update README.md --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1ba6d6e64..2c5e9b899 100644 --- a/README.md +++ b/README.md @@ -254,10 +254,21 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年9月15号 至 2024年 10月13号 商业版代码更新内容** + +550、移除对Sandhook的依赖
+549、移除几处hook,避免部分机型crash
+548、移除无用的goAsync的,避免卸载应用导致ANR
+547、移除部分对1.X的升级处理
+546、修复手机系统升级到13.0+上后,应用列表消失的问题
+ **2024年8月23号 至 2024年 9月14号 商业版代码更新内容** 545、修复IO重定向中一系列函数未对dfd正确处理
+
+2017年 12月 至 2024年 8 月 22 日 商业版代码更新内容(下拉打开)
+ **2024年8月9号 至 2024年 8月22号 商业版代码更新内容** 544、修复Native的一个空指针问题
@@ -285,8 +296,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 528、修复 readlinkat参数问题导致的crash
527、解决某些unity路径检测的问题
-
-2017年 12月 至 2024年 7 月 18 日 商业版代码更新内容(下拉打开)
**2024年7月3号 至 2024年 7月18号 商业版代码更新内容** From 5f9bb46f994256ded7a3f6ecb4065df7ad13eff6 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 12 Oct 2024 17:20:19 +0800 Subject: [PATCH 290/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2c5e9b899..2cf3c1dd2 100644 --- a/README.md +++ b/README.md @@ -258,8 +258,8 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 550、移除对Sandhook的依赖
549、移除几处hook,避免部分机型crash
-548、移除无用的goAsync的,避免卸载应用导致ANR
-547、移除部分对1.X的升级处理
+548、移除未使用到的goAsync,避免ANR
+547、移除部分对1.X的升级处理废弃代码
546、修复手机系统升级到13.0+上后,应用列表消失的问题
**2024年8月23号 至 2024年 9月14号 商业版代码更新内容** From 18273634cd0468e03f89a578d8cff23266250560 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 12 Oct 2024 17:21:10 +0800 Subject: [PATCH 291/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2cf3c1dd2..bb1349cd4 100644 --- a/README.md +++ b/README.md @@ -247,7 +247,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 7. 内置`XPosed Hook`框架 8. 增加定位模拟代码 9. 增加改机代码 -10. 其他400+项问题的修复和改进,详情请见下表 +10. 其他500+项问题的修复和改进,详情请见下表
From 7b4c4cd1dc7e4efd71ed91249a91701f81538bc1 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 29 Oct 2024 14:20:25 +0800 Subject: [PATCH 292/334] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bb1349cd4..7c280c1e6 100644 --- a/README.md +++ b/README.md @@ -254,6 +254,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年10月14号 至 2024年 10月29号 商业版代码更新内容** + +552、所有手机package.ini版本升级到7,避免某些情况下出现应用丢失
+551、修改Demo包名
+ **2024年9月15号 至 2024年 10月13号 商业版代码更新内容** 550、移除对Sandhook的依赖
@@ -262,12 +267,13 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 547、移除部分对1.X的升级处理废弃代码
546、修复手机系统升级到13.0+上后,应用列表消失的问题
+
+2017年 12月 至 2024年 9 月 14 日 商业版代码更新内容(下拉打开)
+ **2024年8月23号 至 2024年 9月14号 商业版代码更新内容** 545、修复IO重定向中一系列函数未对dfd正确处理
-
-2017年 12月 至 2024年 8 月 22 日 商业版代码更新内容(下拉打开)
**2024年8月9号 至 2024年 8月22号 商业版代码更新内容** From 9e1f06d986cd38435d267e4ebcc39c2019261e63 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 29 Oct 2024 14:22:03 +0800 Subject: [PATCH 293/334] Update README_eng.md --- README_eng.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README_eng.md b/README_eng.md index fbb73c8fe..48d77856d 100644 --- a/README_eng.md +++ b/README_eng.md @@ -177,6 +177,7 @@ System version | Whether to support 11.0 | support 12.0 | support 13.0 | support +14.0 | support 15.0 | support
From be4ed0dd727567b5be0c7ba6aefcd0b91ecd6859 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 11 Nov 2024 10:33:09 +0800 Subject: [PATCH 294/334] Update README.md --- README.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7c280c1e6..168d634c1 100644 --- a/README.md +++ b/README.md @@ -239,26 +239,36 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 ------ 1. 兼容最新Android 15.0 -2. 不易被杀毒软件误报 -3. 框架优化,性能大幅提升 -4. 手机系统及APP兼容性大幅提升 -5. 完美运行Google服务 -6. 支持运行纯64位App -7. 内置`XPosed Hook`框架 -8. 增加定位模拟代码 -9. 增加改机代码 -10. 其他500+项问题的修复和改进,详情请见下表 +2. 支持Seccomp-Bpf拦截 +3. 不易被杀毒软件误报 +4. 框架优化,性能大幅提升 +5. 手机系统及APP兼容性大幅提升 +6. 完美运行Google服务 +7. 支持运行纯64位App +8. 内置`XPosed Hook`框架 +9. 增加定位模拟代码 +10. 增加改机代码 +11. 其他500+项问题的修复和改进,详情请见下表
2017年-2024年商业版代码更新详细 ------ +**2024年10月31号 至 2024年 11月11号 商业版代码更新内容** + +555、新功能:增加Seccomp-Bpf支持,实现更底层的拦截
+554、增加对部分加固APP的支持
+553、系统OTA升级时对Split Apks重新安装
+ **2024年10月14号 至 2024年 10月29号 商业版代码更新内容** 552、所有手机package.ini版本升级到7,避免某些情况下出现应用丢失
551、修改Demo包名
+
+2017年 12月 至 2024年 9 月 14 日 商业版代码更新内容(下拉打开)
+ **2024年9月15号 至 2024年 10月13号 商业版代码更新内容** 550、移除对Sandhook的依赖
@@ -267,8 +277,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 547、移除部分对1.X的升级处理废弃代码
546、修复手机系统升级到13.0+上后,应用列表消失的问题
-
-2017年 12月 至 2024年 9 月 14 日 商业版代码更新内容(下拉打开)
**2024年8月23号 至 2024年 9月14号 商业版代码更新内容** From 28bffea6f170becd0109e70b687a0aa36a4b6aa3 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 11 Nov 2024 10:33:44 +0800 Subject: [PATCH 295/334] Update README_eng.md --- README_eng.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/README_eng.md b/README_eng.md index 48d77856d..1189e70ea 100644 --- a/README_eng.md +++ b/README_eng.md @@ -234,15 +234,16 @@ Major updates of the business version ------ 1. Support Android 15.0 -2. Not easily misreported by anti-virus software -3. Framework optimization, performance greatly improved -4. Mobile system and APP compatibility greatly improved -5. Run Google services perfectly -6. Supports running pure 64-bit Apps -7. Built-in `XPosed Hook` framework -8. Add positioning mock code -9. Add code to change device -10. Nearly 500 other fixes and improvements +2. Seccomp-Bpf Support. +3. Not easily misreported by anti-virus software +4. Framework optimization, performance greatly improved +5. Mobile system and APP compatibility greatly improved +6. Run Google services perfectly +7. Supports running pure 64-bit Apps +8. Built-in `XPosed Hook` framework +9. Add positioning mock code +10. Add code to change device +11. Nearly 500 other fixes and improvements
From 4159eedb464215cceaa1abd746d6c04a987fee45 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 25 Nov 2024 10:02:03 +0800 Subject: [PATCH 296/334] Update README.md --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 168d634c1..f1a15da42 100644 --- a/README.md +++ b/README.md @@ -255,19 +255,28 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年11月12号 至 2024年 11月26号 商业版代码更新内容** + +560、重定向路径调整
+559、适配fixupAppDir
+558、reverseRedirectedPath增加检查,防止路径多次重复转换
+557、修复splitNames信息缺失导致部分应用无法正常使用
+556、补充一批normal权限,解决部分APP因为权限丢失无法正常使用的问题
+ **2024年10月31号 至 2024年 11月11号 商业版代码更新内容** 555、新功能:增加Seccomp-Bpf支持,实现更底层的拦截
554、增加对部分加固APP的支持
553、系统OTA升级时对Split Apks重新安装
+
+2017年 12月 至 2024年 10 月 31 日 商业版代码更新内容(下拉打开)
+ **2024年10月14号 至 2024年 10月29号 商业版代码更新内容** 552、所有手机package.ini版本升级到7,避免某些情况下出现应用丢失
551、修改Demo包名
-
-2017年 12月 至 2024年 9 月 14 日 商业版代码更新内容(下拉打开)
**2024年9月15号 至 2024年 10月13号 商业版代码更新内容** From e689e15e3864596979019d57d3e128885a711dca Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 25 Nov 2024 10:07:40 +0800 Subject: [PATCH 297/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1a15da42..e68a1fe59 100644 --- a/README.md +++ b/README.md @@ -257,7 +257,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2024年11月12号 至 2024年 11月26号 商业版代码更新内容** -560、重定向路径调整
+560、重定向路径调整,区分/data/data/com.xxx以及/data/user/0/com.xxx,使其更符合APP使用实际使用的路径
559、适配fixupAppDir
558、reverseRedirectedPath增加检查,防止路径多次重复转换
557、修复splitNames信息缺失导致部分应用无法正常使用
From b5a43e1322789ad87d716c5ffee807122364162b Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 5 Dec 2024 17:42:47 +0800 Subject: [PATCH 298/334] Update README.md --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e68a1fe59..d8bd9024c 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,15 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年11月27号 至 2024年 12月6号 商业版代码更新内容** + +566、修复release打包后IJobService中的onNetworkChanged等几个函数被混淆导致找不到crash的问题
+565、修复由于BluetoothAdapter.sService为null导致IBluetooth hook失败的问题
+564、修复packagesettings被覆盖的问题
+563、删除getCallingUid()中的缓存代码
+562、Seccomp条件判断时处理Application.name为Null的情况
+561、AGP升级到8.2.0
+ **2024年11月12号 至 2024年 11月26号 商业版代码更新内容** 560、重定向路径调整,区分/data/data/com.xxx以及/data/user/0/com.xxx,使其更符合APP使用实际使用的路径
@@ -263,14 +272,15 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 557、修复splitNames信息缺失导致部分应用无法正常使用
556、补充一批normal权限,解决部分APP因为权限丢失无法正常使用的问题
+
+2017年 12月 至 2024年 11 月 11 日 商业版代码更新内容(下拉打开)
+ **2024年10月31号 至 2024年 11月11号 商业版代码更新内容** 555、新功能:增加Seccomp-Bpf支持,实现更底层的拦截
554、增加对部分加固APP的支持
553、系统OTA升级时对Split Apks重新安装
-
-2017年 12月 至 2024年 10 月 31 日 商业版代码更新内容(下拉打开)
**2024年10月14号 至 2024年 10月29号 商业版代码更新内容** From 1420099b88e00f415ff72000a0d62600dcb20047 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 19 Dec 2024 11:43:18 +0800 Subject: [PATCH 299/334] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d8bd9024c..58f1828e2 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2024年商业版代码更新详细 ------ +**2024年12月7号 至 2024年 12月20号 商业版代码更新内容** + +568、修复startIntentSenderFoeResult无法工作的问题
+567、修复GMS由于StatsManager无法hook导致crash的问题
+ **2024年11月27号 至 2024年 12月6号 商业版代码更新内容** 566、修复release打包后IJobService中的onNetworkChanged等几个函数被混淆导致找不到crash的问题
@@ -264,6 +269,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 562、Seccomp条件判断时处理Application.name为Null的情况
561、AGP升级到8.2.0
+
+2017年 12月 至 2024年 11 月 26 日 商业版代码更新内容(下拉打开)
+ **2024年11月12号 至 2024年 11月26号 商业版代码更新内容** 560、重定向路径调整,区分/data/data/com.xxx以及/data/user/0/com.xxx,使其更符合APP使用实际使用的路径
@@ -272,8 +280,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 557、修复splitNames信息缺失导致部分应用无法正常使用
556、补充一批normal权限,解决部分APP因为权限丢失无法正常使用的问题
-
-2017年 12月 至 2024年 11 月 11 日 商业版代码更新内容(下拉打开)
**2024年10月31号 至 2024年 11月11号 商业版代码更新内容** From 2e151d21e33fcd41e5fb3470c71aed208adc3287 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 7 Jan 2025 13:56:13 +0800 Subject: [PATCH 300/334] Update README.md --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 58f1828e2..11d2cdf99 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ VA开发文档请参考:[开发文档](doc/VADev.md) 授权说明 ------ -VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原:济宁市罗盒网络科技有限公司),于2015年至2024年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` +VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原:济宁市罗盒网络科技有限公司),于2015年至2025年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
负责人:张总
@@ -252,14 +252,24 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原
-2017年-2024年商业版代码更新详细 +2017年-2025年商业版代码更新详细 ------ +**2024年12月21号 至 2025年 1月7号 商业版代码更新内容** + +572、Seccomp-bpf支持32位
+571、修复某些情况下路径多次重定向的问题
+570、修复抖音人脸识别时可能白屏的问题
+569、去掉几年前为抖音打不开做的一些修改br/> + **2024年12月7号 至 2024年 12月20号 商业版代码更新内容** 568、修复startIntentSenderFoeResult无法工作的问题
567、修复GMS由于StatsManager无法hook导致crash的问题
+
+2017年 12月 至 2024年 12 月 6 日 商业版代码更新内容(下拉打开)
+ **2024年11月27号 至 2024年 12月6号 商业版代码更新内容** 566、修复release打包后IJobService中的onNetworkChanged等几个函数被混淆导致找不到crash的问题
@@ -269,9 +279,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 562、Seccomp条件判断时处理Application.name为Null的情况
561、AGP升级到8.2.0
-
-2017年 12月 至 2024年 11 月 26 日 商业版代码更新内容(下拉打开)
- **2024年11月12号 至 2024年 11月26号 商业版代码更新内容** 560、重定向路径调整,区分/data/data/com.xxx以及/data/user/0/com.xxx,使其更符合APP使用实际使用的路径
From 10a28066205f71c0ea0cd69e02447f9c709aecf5 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 7 Jan 2025 13:57:18 +0800 Subject: [PATCH 301/334] Update README_eng.md --- README_eng.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_eng.md b/README_eng.md index 1189e70ea..93312074c 100644 --- a/README_eng.md +++ b/README_eng.md @@ -214,7 +214,7 @@ Please refer to the VA development documentation:[Development document](doc/VA License Instructions ------ -VirtualApp virtual machine technology belongs to: Jining Luohe Network Technology Co., LTD. It applied for several VirtualApp intellectual property rights from 2015 to 2023 and` is protected by the Intellectual property Law of the People's Republic of China`.When you need to use the code on Github, **please purchase a business license**,and receive the full source code of the latest VirtualApp business version.Hundreds of licensed customers are paying to use the business version of VirtualApp code, and the app integrated with VirtualApp code is launched more than 200 million times a day. Many Android engineers provided us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, VirtualApp Business Edition code has better performance and higher compatibility. `The company of that year will become one of them after obtaining the license, and enjoy the technological achievements after the continuous iteration. And we can interact and collaborate with our licensed customers operationally, technically and commercially.` +VirtualApp virtual machine technology belongs to: Jining Luohe Network Technology Co., LTD. It applied for several VirtualApp intellectual property rights from 2015 to 2025 and` is protected by the Intellectual property Law of the People's Republic of China`.When you need to use the code on Github, **please purchase a business license**,and receive the full source code of the latest VirtualApp business version.Hundreds of licensed customers are paying to use the business version of VirtualApp code, and the app integrated with VirtualApp code is launched more than 200 million times a day. Many Android engineers provided us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, VirtualApp Business Edition code has better performance and higher compatibility. `The company of that year will become one of them after obtaining the license, and enjoy the technological achievements after the continuous iteration. And we can interact and collaborate with our licensed customers operationally, technically and commercially.`
Person in charge: Mr. Zhang
From bb7b0aed916830c8640ed0e9e7a6002e103b6775 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 7 Jan 2025 13:58:14 +0800 Subject: [PATCH 302/334] Update README_eng.md --- README_eng.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_eng.md b/README_eng.md index 93312074c..9bc680de3 100644 --- a/README_eng.md +++ b/README_eng.md @@ -243,7 +243,7 @@ Major updates of the business version 8. Built-in `XPosed Hook` framework 9. Add positioning mock code 10. Add code to change device -11. Nearly 500 other fixes and improvements +11. Nearly 600 other fixes and improvements
From 3566da7eced13cb67c65f35398af148ad6ca3785 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 22 Jan 2025 14:16:58 +0800 Subject: [PATCH 303/334] Update README.md --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 11d2cdf99..a755d86f2 100644 --- a/README.md +++ b/README.md @@ -255,20 +255,33 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年1月8号 至 2025年 1月23号 商业版代码更新内容** + +580、installer静默安装部分适配
+579、修复静态广播收不到消息
+578、修复pending intent数据丢失问题
+577、input manager 14.0+上的适配
+576、蓝牙适配
+575、queryStatsForPackage适配
+574、修复有些手机上显示不出应用列表
+573、其他一些小问题适配
+ **2024年12月21号 至 2025年 1月7号 商业版代码更新内容** 572、Seccomp-bpf支持32位
571、修复某些情况下路径多次重定向的问题
570、修复抖音人脸识别时可能白屏的问题
-569、去掉几年前为抖音打不开做的一些修改br/> +569、去掉几年前为抖音打不开做的一些修改
+ +
+2017年 12月 至 2024年 12 月 20 日 商业版代码更新内容(下拉打开)
+ **2024年12月7号 至 2024年 12月20号 商业版代码更新内容** 568、修复startIntentSenderFoeResult无法工作的问题
567、修复GMS由于StatsManager无法hook导致crash的问题
-
-2017年 12月 至 2024年 12 月 6 日 商业版代码更新内容(下拉打开)
**2024年11月27号 至 2024年 12月6号 商业版代码更新内容** From 9e70acfa38a853dc0d0effe1a1ce123cc37fdfc1 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sat, 8 Feb 2025 14:51:29 +0800 Subject: [PATCH 304/334] Update README.md --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a755d86f2..565c4f7c6 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年1月24号 至 2025年 2月10号 商业版代码更新内容** + +581、对IO进行inline hook时暂停所有Java线程,避免冷启动时因多线程导致的低概率crash
+ + **2025年1月8号 至 2025年 1月23号 商业版代码更新内容** 580、installer静默安装部分适配
@@ -266,6 +271,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 574、修复有些手机上显示不出应用列表
573、其他一些小问题适配
+ +
+2017年 12月 至 2025年 1 月 7 日 商业版代码更新内容(下拉打开)
+ + **2024年12月21号 至 2025年 1月7号 商业版代码更新内容** 572、Seccomp-bpf支持32位
@@ -273,9 +283,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 570、修复抖音人脸识别时可能白屏的问题
569、去掉几年前为抖音打不开做的一些修改
-
-2017年 12月 至 2024年 12 月 20 日 商业版代码更新内容(下拉打开)
- **2024年12月7号 至 2024年 12月20号 商业版代码更新内容** From ddb31d155d79eda38513e18f97ab5a5fc398571e Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 26 Feb 2025 15:05:34 +0800 Subject: [PATCH 305/334] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 565c4f7c6..19baaf83b 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,10 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年2月11号 至 2025年 2月27号 商业版代码更新内容** + +582、适配最新版微信
+ **2025年1月24号 至 2025年 2月10号 商业版代码更新内容** 581、对IO进行inline hook时暂停所有Java线程,避免冷启动时因多线程导致的低概率crash
From 5733d09506efd798f2e5e90a4c1b511c12e7f200 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 18 Mar 2025 11:05:15 +0800 Subject: [PATCH 306/334] Update README.md --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 19baaf83b..809b27119 100644 --- a/README.md +++ b/README.md @@ -255,10 +255,20 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年2月18号 至 2025年 3月19号 商业版代码更新内容** + +586、seccomp 相关的调整
+585、修改微信在14.0+上开启seccomp-bpfcrash的问题
+584、新增对StorageStatsManager的适配
+583、UsageStatsManager相关API适配
+ **2025年2月11号 至 2025年 2月27号 商业版代码更新内容** 582、适配最新版微信
+
+2017年 12月 至 2025年 2 月 10 日 商业版代码更新内容(下拉打开)
+ **2025年1月24号 至 2025年 2月10号 商业版代码更新内容** 581、对IO进行inline hook时暂停所有Java线程,避免冷启动时因多线程导致的低概率crash
@@ -276,10 +286,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 573、其他一些小问题适配
-
-2017年 12月 至 2025年 1 月 7 日 商业版代码更新内容(下拉打开)
- - **2024年12月21号 至 2025年 1月7号 商业版代码更新内容** 572、Seccomp-bpf支持32位
From 8467d315d3396b08bfed6e83229d91316f1f14be Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 18 Mar 2025 11:06:22 +0800 Subject: [PATCH 307/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 809b27119..340f326f8 100644 --- a/README.md +++ b/README.md @@ -258,7 +258,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2025年2月18号 至 2025年 3月19号 商业版代码更新内容** 586、seccomp 相关的调整
-585、修改微信在14.0+上开启seccomp-bpfcrash的问题
+585、修复微信在14.0+上开启seccomp-bpf无法打开的问题
584、新增对StorageStatsManager的适配
583、UsageStatsManager相关API适配
From 794888d3e6b4ff07faf670c80f6faf559d10130d Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 18 Mar 2025 13:41:36 +0800 Subject: [PATCH 308/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 340f326f8..ce38cf16a 100644 --- a/README.md +++ b/README.md @@ -255,7 +255,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ -**2025年2月18号 至 2025年 3月19号 商业版代码更新内容** +**2025年2月28号 至 2025年 3月19号 商业版代码更新内容** 586、seccomp 相关的调整
585、修复微信在14.0+上开启seccomp-bpf无法打开的问题
From 9b4899257d2afd2f45a3a0b7b256f83488e939bf Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 25 Mar 2025 16:14:31 +0800 Subject: [PATCH 309/334] Update README.md --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ce38cf16a..1d362dd4f 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,14 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年3月20号 至 2025年 3月26号 商业版代码更新内容** + +590、增加对AppSearchManager的适配
+589、增加对DomainVerificationManager的适配
+588、增加对SystemUpdateManager的适配
+587、修复多个进程同时启动同一个进程时的crash问题
+ + **2025年2月28号 至 2025年 3月19号 商业版代码更新内容** 586、seccomp 相关的调整
@@ -262,12 +270,13 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 584、新增对StorageStatsManager的适配
583、UsageStatsManager相关API适配
+
+2017年 12月 至 2025年 2 月 27 日 商业版代码更新内容(下拉打开)
+ **2025年2月11号 至 2025年 2月27号 商业版代码更新内容** 582、适配最新版微信
-
-2017年 12月 至 2025年 2 月 10 日 商业版代码更新内容(下拉打开)
**2025年1月24号 至 2025年 2月10号 商业版代码更新内容** From f2e56ef5243b5da189804989cb1fbf2ec004bd7f Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 14 Apr 2025 10:03:58 +0800 Subject: [PATCH 310/334] Update README.md --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1d362dd4f..de7907c2d 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,13 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年3月27号 至 2025年 4月15号 商业版代码更新内容** + +594、修复GMS无法调起登录的问题
+593、增加对IInputMethodManagerGlobalInvoker的hook
+592、修复工作空间中无法打开VAPP的问题
+591、适配微信8.0.57
+ **2025年3月20号 至 2025年 3月26号 商业版代码更新内容** 590、增加对AppSearchManager的适配
@@ -262,6 +269,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 588、增加对SystemUpdateManager的适配
587、修复多个进程同时启动同一个进程时的crash问题
+
+2017年 12月 至 2025年 3 月 19 日 商业版代码更新内容(下拉打开)
+ **2025年2月28号 至 2025年 3月19号 商业版代码更新内容** @@ -270,9 +280,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 584、新增对StorageStatsManager的适配
583、UsageStatsManager相关API适配
-
-2017年 12月 至 2025年 2 月 27 日 商业版代码更新内容(下拉打开)
- **2025年2月11号 至 2025年 2月27号 商业版代码更新内容** 582、适配最新版微信
From 63ad851ebfc4dcc5341a2db5415449a11234e8a7 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 29 Apr 2025 21:25:29 +0800 Subject: [PATCH 311/334] Update README.md --- README.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index de7907c2d..96b5aa6ac 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ VA的其他特性 进程级“虚拟机”,VA独特的实现方式让其性能几乎于原生App一致,更不需要普通虚拟机漫长的启动。 - 全版本支持
-支持5.0-15.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 +支持5.0-16.0,支持32位/64位app,支持ARM以及X86处理器。并且支持未来将更新的Android版本。 - 易扩展与集成
VA 的集成方式与普通Android库类似,即使您的App已经完成上线,您也方便的可以集成VA,享受VA带来的能力。 @@ -183,6 +183,7 @@ VA已被**上百家**企业进行了广泛测试,包含**数十家上市公司 13.0 | 支持 14.0 | 支持 15.0 | 支持 +16.0 | 支持
@@ -238,7 +239,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 商业版主要更新 ------ -1. 兼容最新Android 15.0 +1. 兼容最新Android 16.0 2. 支持Seccomp-Bpf拦截 3. 不易被杀毒软件误报 4. 框架优化,性能大幅提升 @@ -248,13 +249,25 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 8. 内置`XPosed Hook`框架 9. 增加定位模拟代码 10. 增加改机代码 -11. 其他500+项问题的修复和改进,详情请见下表 +11. 其他600+项问题的修复和改进,详情请见下表
2017年-2025年商业版代码更新详细 ------ +**2025年4月16号 至 2025年 4月30号 商业版代码更新内容** + +602、Android 16.0 beta 4 适配
+601、完善seccomp-bpf重定向相关的功能
+600、增加配置可以让APP只使用seccomp-bpf,不使用inline hook
+599、将target sdk升级到34
+598、修复va core进程由于client为空导致的crash
+597、启动进程的时候增加重试,避免在某些机型上由于进程死亡太频繁导致无法启动进程
+596、对于某类型加固后是否需要安装provider的部分改为动态判断
+595、修复demo在某些设备上由于title为null导致的crash
+ + **2025年3月27号 至 2025年 4月15号 商业版代码更新内容** 594、修复GMS无法调起登录的问题
@@ -262,6 +275,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 592、修复工作空间中无法打开VAPP的问题
591、适配微信8.0.57
+
+2017年 12月 至 2025年 3 月 26 日 商业版代码更新内容(下拉打开)
+ **2025年3月20号 至 2025年 3月26号 商业版代码更新内容** 590、增加对AppSearchManager的适配
@@ -269,9 +285,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 588、增加对SystemUpdateManager的适配
587、修复多个进程同时启动同一个进程时的crash问题
-
-2017年 12月 至 2025年 3 月 19 日 商业版代码更新内容(下拉打开)
- **2025年2月28号 至 2025年 3月19号 商业版代码更新内容** From 8e95b186d5596f74f047438688bbfdaf87b3cd48 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 29 Apr 2025 21:27:03 +0800 Subject: [PATCH 312/334] Update README_eng.md --- README_eng.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README_eng.md b/README_eng.md index 9bc680de3..2f45e1ff1 100644 --- a/README_eng.md +++ b/README_eng.md @@ -131,7 +131,7 @@ VA Other features Process-level "virtual machine", VA's unique implementation model makes its performance almost the same as that of the native APP, and does not need a long startup of ordinary virtual machines. - Full version support
-Support 5.0-15.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. +Support 5.0-16.0, 32-bit/64-bit APP, ARM and X86 processor. And support Android version in the future which will be updated. - Easy Expansion and Integration
The integration of VA is similar to the normal Android library, even if your APP has been online, you can conveniently integrate VA and enjoy the capability brought by VA. @@ -179,6 +179,7 @@ System version | Whether to support 13.0 | support 14.0 | support 15.0 | support +16.0 | support
@@ -233,8 +234,8 @@ If you use VirtualApp for **internal use, business profit or upload it to the ap Major updates of the business version ------ -1. Support Android 15.0 -2. Seccomp-Bpf Support. +1. Support Android 16.0 +2. Support Seccomp-Bpf. 3. Not easily misreported by anti-virus software 4. Framework optimization, performance greatly improved 5. Mobile system and APP compatibility greatly improved From b22d2db7ffccd580fe99e1fcb9ab8d0befa0b176 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 20 May 2025 10:42:26 +0800 Subject: [PATCH 313/334] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 96b5aa6ac..28a21f80b 100644 --- a/README.md +++ b/README.md @@ -256,6 +256,10 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年5月1号 至 2025年 6月30号 商业版代码更新内容** + +正在开发新的Java层代理方案,预计对稳定性和兼容性会有比较大的改善~
+ **2025年4月16号 至 2025年 4月30号 商业版代码更新内容** 602、Android 16.0 beta 4 适配
From af2fbd85c3e77719596a350191cf68690ef096a4 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 1 Jul 2025 18:32:05 +0800 Subject: [PATCH 314/334] Update README.md --- README.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 28a21f80b..466e594b4 100644 --- a/README.md +++ b/README.md @@ -240,29 +240,31 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 ------ 1. 兼容最新Android 16.0 -2. 支持Seccomp-Bpf拦截 -3. 不易被杀毒软件误报 -4. 框架优化,性能大幅提升 -5. 手机系统及APP兼容性大幅提升 -6. 完美运行Google服务 -7. 支持运行纯64位App -8. 内置`XPosed Hook`框架 -9. 增加定位模拟代码 -10. 增加改机代码 -11. 其他600+项问题的修复和改进,详情请见下表 +2. 支持Binder拦截方案(非动态代理方案) +3. 支持Seccomp-Bpf拦截 +4. 不易被杀毒软件误报 +5. 框架优化,性能大幅提升 +6. 手机系统及APP兼容性大幅提升 +7. 完美运行Google服务 +8. 支持运行纯64位App +9. 内置`XPosed Hook`框架 +10. 增加定位模拟代码 +11. 增加改机代码 +12. 其他600+项问题的修复和改进,详情请见下表
2017年-2025年商业版代码更新详细 ------ -**2025年5月1号 至 2025年 6月30号 商业版代码更新内容** +**2025年5月1号 至 2025年 7月2号 商业版代码更新内容** -正在开发新的Java层代理方案,预计对稳定性和兼容性会有比较大的改善~
+604、新功能开发:基于拦截Binder来实现对系统AIDL调用的拦截
+603、16.0最新版本继续适配
**2025年4月16号 至 2025年 4月30号 商业版代码更新内容** -602、Android 16.0 beta 4 适配
+602、对Android 16.0 beta 4 适配
601、完善seccomp-bpf重定向相关的功能
600、增加配置可以让APP只使用seccomp-bpf,不使用inline hook
599、将target sdk升级到34
From 65f1eeb88ba492c64b5bb88d9d491511a5ab04bb Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 1 Jul 2025 18:33:05 +0800 Subject: [PATCH 315/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 466e594b4..7607ba3f7 100644 --- a/README.md +++ b/README.md @@ -240,7 +240,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 ------ 1. 兼容最新Android 16.0 -2. 支持Binder拦截方案(非动态代理方案) +2. 支持Binder拦截,不再使用动态代理 3. 支持Seccomp-Bpf拦截 4. 不易被杀毒软件误报 5. 框架优化,性能大幅提升 From 6126fa139b9d4d65314569a8fd6445485b7cb82c Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 1 Jul 2025 18:34:17 +0800 Subject: [PATCH 316/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7607ba3f7..fa73e8d71 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2025年5月1号 至 2025年 7月2号 商业版代码更新内容** -604、新功能开发:基于拦截Binder来实现对系统AIDL调用的拦截
+604、新功能开发:基于拦截Binder的方式来实现对系统AIDL调用的拦截
603、16.0最新版本继续适配
**2025年4月16号 至 2025年 4月30号 商业版代码更新内容** From 7a2949567aff9b8b817a1971a3dfb5748c63357a Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 1 Jul 2025 18:36:08 +0800 Subject: [PATCH 317/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa73e8d71..018513193 100644 --- a/README.md +++ b/README.md @@ -259,9 +259,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2025年5月1号 至 2025年 7月2号 商业版代码更新内容** -604、新功能开发:基于拦截Binder的方式来实现对系统AIDL调用的拦截
+604、新功能开发:基于拦截Binder的方式来实现对系统AIDL调用的拦截。通过这种方式可不再使用动态代理,对于稳定性将会有比较大提升
603、16.0最新版本继续适配
- +、新功能开发:基于拦截Binder的方式来实 **2025年4月16号 至 2025年 4月30号 商业版代码更新内容** 602、对Android 16.0 beta 4 适配
From b17b0efeafb749e80694c5a07113ecd0d2866458 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 1 Jul 2025 18:37:21 +0800 Subject: [PATCH 318/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 018513193..33ebfb059 100644 --- a/README.md +++ b/README.md @@ -261,7 +261,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 604、新功能开发:基于拦截Binder的方式来实现对系统AIDL调用的拦截。通过这种方式可不再使用动态代理,对于稳定性将会有比较大提升
603、16.0最新版本继续适配
-、新功能开发:基于拦截Binder的方式来实 + **2025年4月16号 至 2025年 4月30号 商业版代码更新内容** 602、对Android 16.0 beta 4 适配
From 39efbbc7d0f5210d3698a8dbdff039ef58860fbf Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 21 Jul 2025 11:55:24 +0800 Subject: [PATCH 319/334] Update README.md --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 33ebfb059..7f213dae6 100644 --- a/README.md +++ b/README.md @@ -257,11 +257,19 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年7月3号 至 2025年 7月21 商业版代码更新内容** + +606、与新功能相关的路径处理
+605、一些bug处理
+ **2025年5月1号 至 2025年 7月2号 商业版代码更新内容** 604、新功能开发:基于拦截Binder的方式来实现对系统AIDL调用的拦截。通过这种方式可不再使用动态代理,对于稳定性将会有比较大提升
603、16.0最新版本继续适配
+
+2017年 12月 至 2025年 4 月 30 日 商业版代码更新内容(下拉打开)
+ **2025年4月16号 至 2025年 4月30号 商业版代码更新内容** 602、对Android 16.0 beta 4 适配
@@ -281,9 +289,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 592、修复工作空间中无法打开VAPP的问题
591、适配微信8.0.57
-
-2017年 12月 至 2025年 3 月 26 日 商业版代码更新内容(下拉打开)
- **2025年3月20号 至 2025年 3月26号 商业版代码更新内容** 590、增加对AppSearchManager的适配
From e7359c0a7d54bc3c6e8f45cd3cdcf9cee2d08e50 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Fri, 8 Aug 2025 17:49:25 +0800 Subject: [PATCH 320/334] Update README.md --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7f213dae6..43c329c70 100644 --- a/README.md +++ b/README.md @@ -257,18 +257,27 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年7月22号 至 2025年 8月8 商业版代码更新内容** + +610、增加对INetworkScoreService的处理
+609、修复新功能在release下的一些错误
+608、修复某些手机上新功能无法打开APP
+607、修复Tethering相关的crash + + **2025年7月3号 至 2025年 7月21 商业版代码更新内容** 606、与新功能相关的路径处理
605、一些bug处理
+
+2017年 12月 至 2025年 7 月 2 日 商业版代码更新内容(下拉打开)
+ **2025年5月1号 至 2025年 7月2号 商业版代码更新内容** 604、新功能开发:基于拦截Binder的方式来实现对系统AIDL调用的拦截。通过这种方式可不再使用动态代理,对于稳定性将会有比较大提升
603、16.0最新版本继续适配
-
-2017年 12月 至 2025年 4 月 30 日 商业版代码更新内容(下拉打开)
**2025年4月16号 至 2025年 4月30号 商业版代码更新内容** From 81134cb3e236d947f9244438582d91524ef34331 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Sun, 31 Aug 2025 22:16:31 +0800 Subject: [PATCH 321/334] Update README.md --- README.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 43c329c70..953e4979d 100644 --- a/README.md +++ b/README.md @@ -257,22 +257,30 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ -**2025年7月22号 至 2025年 8月8 商业版代码更新内容** +**2025年8月9号 至 2025年 9月1号 商业版代码更新内容** + +616、增加对setxattr/lsetxattr/bind/connect/syscall等几个libc api处理
+615、增加对execve启动的进程实现inline hook
+614、增加可对application中的全部路径模拟为系统安装路径
+613、增加对logcat等命令的过滤处理
+612、修复app 崩溃/anr等系列问题
+611、修复ParceledListSlice.getList返回Null的问题
+ +**2025年7月22号 至 2025年 8月8号 商业版代码更新内容** 610、增加对INetworkScoreService的处理
609、修复新功能在release下的一些错误
608、修复某些手机上新功能无法打开APP
607、修复Tethering相关的crash +
+2017年 12月 至 2025年 7 月 21 日 商业版代码更新内容(下拉打开)
**2025年7月3号 至 2025年 7月21 商业版代码更新内容** 606、与新功能相关的路径处理
605、一些bug处理
-
-2017年 12月 至 2025年 7 月 2 日 商业版代码更新内容(下拉打开)
- **2025年5月1号 至 2025年 7月2号 商业版代码更新内容** 604、新功能开发:基于拦截Binder的方式来实现对系统AIDL调用的拦截。通过这种方式可不再使用动态代理,对于稳定性将会有比较大提升
From 78abc55e9f83f78f7164363ac6cc8dc3c1b0ae02 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 16 Sep 2025 11:28:30 +0800 Subject: [PATCH 322/334] Update README.md --- README.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 953e4979d..0b4ed3af3 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,21 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年9月2号 至 2025年 9月17号 商业版代码更新内容** + +627、Android 16kb page size 适配
+626、fix蓝牙几个代理类的代码错误
+625、处理某些APP在Application->attach中获取到宿主Application的场景
+624、处理Activity referrer相关的
+623、处理processOutsideIntent时intent包含vapp class的情况
+622、针对某些oppo 13.0机型适配
+621、处理调用ArrayUtils.indexOf时,有的地方按0开始起步有的地方按1开始起步导致异常,都统一为1
+620、适配LockSettings/WifiScanner/NetworkScoreManager/WifiManager/SensitiveContentProtectionManager等几个manager
+619、新功能模式下BinderProxyInjectManager.addInjector增加判断,避免有些因为class不存在导致crash
+618、新功能模式下支持Instrumentation注入
+617、增加对native层获取宿主信息的处理
+ + **2025年8月9号 至 2025年 9月1号 商业版代码更新内容** 616、增加对setxattr/lsetxattr/bind/connect/syscall等几个libc api处理
@@ -266,6 +281,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 612、修复app 崩溃/anr等系列问题
611、修复ParceledListSlice.getList返回Null的问题
+
+2017年 12月 至 2025年 7 月 21 日 商业版代码更新内容(下拉打开)
+ **2025年7月22号 至 2025年 8月8号 商业版代码更新内容** 610、增加对INetworkScoreService的处理
@@ -273,8 +291,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 608、修复某些手机上新功能无法打开APP
607、修复Tethering相关的crash -
-2017年 12月 至 2025年 7 月 21 日 商业版代码更新内容(下拉打开)
**2025年7月3号 至 2025年 7月21 商业版代码更新内容** From 4165f4c465e8de4a687941770004660ea22a62cb Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Thu, 9 Oct 2025 16:26:47 +0800 Subject: [PATCH 323/334] Update README.md --- README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0b4ed3af3..1f3504c8b 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,16 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年9月18号 至 2025年 10月10号 商业版代码更新内容** + +633、处理onNewIntent()中的activity Referrer
+632、适配NotificationProviderPublic
+631、修复15.0+上isDirectlyHandlingTransaction()的多线程处理
+630、隐藏Libcore.os的反射获取
+629、binderproxy模式支持IBatteryStats
+628、适配某些加固APP
+ + **2025年9月2号 至 2025年 9月17号 商业版代码更新内容** 627、Android 16kb page size 适配
@@ -271,6 +281,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 618、新功能模式下支持Instrumentation注入
617、增加对native层获取宿主信息的处理
+
+2017年 12月 至 2025年 9 月 1 日 商业版代码更新内容(下拉打开)
+ **2025年8月9号 至 2025年 9月1号 商业版代码更新内容** @@ -281,9 +294,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 612、修复app 崩溃/anr等系列问题
611、修复ParceledListSlice.getList返回Null的问题
-
-2017年 12月 至 2025年 7 月 21 日 商业版代码更新内容(下拉打开)
- **2025年7月22号 至 2025年 8月8号 商业版代码更新内容** 610、增加对INetworkScoreService的处理
From 4d97ce0dd2d381f52bc679ce6c0afc347a96c6e9 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 28 Oct 2025 11:15:38 +0800 Subject: [PATCH 324/334] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1f3504c8b..f2220cda5 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,10 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年10月11号 至 2025年 10月28号 商业版代码更新内容** + +634、修复IBatteryStats相关的空指针
+ **2025年9月18号 至 2025年 10月10号 商业版代码更新内容** 633、处理onNewIntent()中的activity Referrer
From 661b0b4d8af970d68a0549e48423991c8485c9db Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Tue, 11 Nov 2025 21:08:37 +0800 Subject: [PATCH 325/334] Update README.md --- README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f2220cda5..1eae11d77 100644 --- a/README.md +++ b/README.md @@ -257,10 +257,19 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年10月29号 至 2025年 11月11号 商业版代码更新内容** + +637、新功能:Seccomp-Bpf下增加了对execve的调用支持
+636、处理了与反射相关的几个地方
+635、对几个内存文件的chmod处理
+ **2025年10月11号 至 2025年 10月28号 商业版代码更新内容** 634、修复IBatteryStats相关的空指针
+
+2017年 12月 至 2025年 10 月 10 日 商业版代码更新内容(下拉打开)
+ **2025年9月18号 至 2025年 10月10号 商业版代码更新内容** 633、处理onNewIntent()中的activity Referrer
@@ -285,9 +294,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 618、新功能模式下支持Instrumentation注入
617、增加对native层获取宿主信息的处理
-
-2017年 12月 至 2025年 9 月 1 日 商业版代码更新内容(下拉打开)
- **2025年8月9号 至 2025年 9月1号 商业版代码更新内容** From 525b014af1c35da78518b13bf7d2e3b545e75dda Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 1 Dec 2025 10:29:53 +0800 Subject: [PATCH 326/334] Update README.md --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1eae11d77..bbd9114c1 100644 --- a/README.md +++ b/README.md @@ -257,19 +257,28 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年11月12号 至 2025年 12月2号 商业版代码更新内容** + +641、新功能:Native层增加机型模拟支持
+640、seccomp-bpf对ptrace的一些处理
+639、修复执行Java命令时进程可能崩溃的问题
+638、修复其他基础崩溃的问题
+ + **2025年10月29号 至 2025年 11月11号 商业版代码更新内容** 637、新功能:Seccomp-Bpf下增加了对execve的调用支持
636、处理了与反射相关的几个地方
635、对几个内存文件的chmod处理
+ +
+2017年 12月 至 2025年 10 月 28 日 商业版代码更新内容(下拉打开)
+ **2025年10月11号 至 2025年 10月28号 商业版代码更新内容** 634、修复IBatteryStats相关的空指针
-
-2017年 12月 至 2025年 10 月 10 日 商业版代码更新内容(下拉打开)
- **2025年9月18号 至 2025年 10月10号 商业版代码更新内容** 633、处理onNewIntent()中的activity Referrer
From 4f23e7a8a7c47f0159c063f98630fb0d8e7fa5fb Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 1 Dec 2025 10:30:59 +0800 Subject: [PATCH 327/334] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bbd9114c1..275a8f214 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,8 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 **2025年11月12号 至 2025年 12月2号 商业版代码更新内容** -641、新功能:Native层增加机型模拟支持
+642、新功能:Native层增加机型模拟支持
+641、支持对应用强制开启机型模拟/强制使用真机信息
640、seccomp-bpf对ptrace的一些处理
639、修复执行Java命令时进程可能崩溃的问题
638、修复其他基础崩溃的问题
From 462957e49bc951e66a57fe978bb9698d232a1eb0 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 1 Dec 2025 10:31:49 +0800 Subject: [PATCH 328/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 275a8f214..ff3439899 100644 --- a/README.md +++ b/README.md @@ -263,7 +263,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 641、支持对应用强制开启机型模拟/强制使用真机信息
640、seccomp-bpf对ptrace的一些处理
639、修复执行Java命令时进程可能崩溃的问题
-638、修复其他基础崩溃的问题
+638、修复其他几处崩溃的问题
**2025年10月29号 至 2025年 11月11号 商业版代码更新内容** From d6a0e9ec108a485551507a1e773e34fc9d82e2fa Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Wed, 17 Dec 2025 14:59:50 +0800 Subject: [PATCH 329/334] Update README.md --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ff3439899..b3de52380 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,13 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ + +**2025年12月3号 至 2025年 12月18号 商业版代码更新内容** + +645、某些svc处理
+644、系统路径调整
+643、maps调整
+ **2025年11月12号 至 2025年 12月2号 商业版代码更新内容** 642、新功能:Native层增加机型模拟支持
@@ -266,16 +273,15 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 638、修复其他几处崩溃的问题
+
+2017年 12月 至 2025年 11 月 11 日 商业版代码更新内容(下拉打开)
+ **2025年10月29号 至 2025年 11月11号 商业版代码更新内容** 637、新功能:Seccomp-Bpf下增加了对execve的调用支持
636、处理了与反射相关的几个地方
635、对几个内存文件的chmod处理
- -
-2017年 12月 至 2025年 10 月 28 日 商业版代码更新内容(下拉打开)
- **2025年10月11号 至 2025年 10月28号 商业版代码更新内容** 634、修复IBatteryStats相关的空指针
From 5afab6182d4e401cd779d020202b0c9f006062f1 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 29 Dec 2025 14:32:14 +0800 Subject: [PATCH 330/334] Update README.md --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b3de52380..8635a275b 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,11 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 2017年-2025年商业版代码更新详细 ------ +**2025年12月19号 至 2025年 12月30号 商业版代码更新内容** + +648、从处理openat2与faccessat2,seccomp等调用
+647、适配APP中对seccomp-bpf的调用
+646、适配某些应用因为监测打不开的问题
**2025年12月3号 至 2025年 12月18号 商业版代码更新内容** @@ -264,6 +269,9 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 644、系统路径调整
643、maps调整
+
+2017年 12月 至 2025年 12 月 2 日 商业版代码更新内容(下拉打开)
+ **2025年11月12号 至 2025年 12月2号 商业版代码更新内容** 642、新功能:Native层增加机型模拟支持
@@ -273,9 +281,6 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 638、修复其他几处崩溃的问题
-
-2017年 12月 至 2025年 11 月 11 日 商业版代码更新内容(下拉打开)
- **2025年10月29号 至 2025年 11月11号 商业版代码更新内容** 637、新功能:Seccomp-Bpf下增加了对execve的调用支持
From f9625487f822d2538716806cb34702a1cd99d666 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 29 Dec 2025 14:33:07 +0800 Subject: [PATCH 331/334] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8635a275b..88d971738 100644 --- a/README.md +++ b/README.md @@ -220,7 +220,7 @@ VA开发文档请参考:[开发文档](doc/VADev.md) 授权说明 ------ -VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原:济宁市罗盒网络科技有限公司),于2015年至2025年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。` +VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原:济宁市罗盒网络科技有限公司),于2015年至2026年申请多项VirtualApp知识产权,`受中华人民共和国知识产权法保护`。当您需要使用Github上的代码时,**请购买商业授权**,获取商业授权后将可以收到最新VirtualApp商业版全部源代码。上百家授权客户在付费使用VirtualApp商业版代码,集成VirtualApp代码的APP日启动次数超过2亿次,众多安卓工程师向我们提供不同场景下的用户反馈,通过我们技术团队不断优化迭代,VirtualApp商业版代码性能更好、兼容性更高。`当您的公司获取授权后,将成为其中一员,享受这些不断迭代完善后的技术成果。并可以和我们的授权客户进行运营、技术及商业上的互动合作。`
负责人:张总
@@ -254,7 +254,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原
-2017年-2025年商业版代码更新详细 +2017年-2026年商业版代码更新详细 ------ **2025年12月19号 至 2025年 12月30号 商业版代码更新内容** From b96b7f5afecadf4972cca72620e69a95fbb1d0f2 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 29 Dec 2025 14:33:53 +0800 Subject: [PATCH 332/334] Update README_eng.md --- README_eng.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_eng.md b/README_eng.md index 2f45e1ff1..7bfae4169 100644 --- a/README_eng.md +++ b/README_eng.md @@ -215,7 +215,7 @@ Please refer to the VA development documentation:[Development document](doc/VA License Instructions ------ -VirtualApp virtual machine technology belongs to: Jining Luohe Network Technology Co., LTD. It applied for several VirtualApp intellectual property rights from 2015 to 2025 and` is protected by the Intellectual property Law of the People's Republic of China`.When you need to use the code on Github, **please purchase a business license**,and receive the full source code of the latest VirtualApp business version.Hundreds of licensed customers are paying to use the business version of VirtualApp code, and the app integrated with VirtualApp code is launched more than 200 million times a day. Many Android engineers provided us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, VirtualApp Business Edition code has better performance and higher compatibility. `The company of that year will become one of them after obtaining the license, and enjoy the technological achievements after the continuous iteration. And we can interact and collaborate with our licensed customers operationally, technically and commercially.` +VirtualApp virtual machine technology belongs to: Jining Luohe Network Technology Co., LTD. It applied for several VirtualApp intellectual property rights from 2015 to 2026 and` is protected by the Intellectual property Law of the People's Republic of China`.When you need to use the code on Github, **please purchase a business license**,and receive the full source code of the latest VirtualApp business version.Hundreds of licensed customers are paying to use the business version of VirtualApp code, and the app integrated with VirtualApp code is launched more than 200 million times a day. Many Android engineers provided us with user feedback in different scenarios, and through our technical team's continuous optimization and iteration, VirtualApp Business Edition code has better performance and higher compatibility. `The company of that year will become one of them after obtaining the license, and enjoy the technological achievements after the continuous iteration. And we can interact and collaborate with our licensed customers operationally, technically and commercially.`
Person in charge: Mr. Zhang
From ed9f6c919b06a07c154c262ba43499cbe563e08f Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 29 Dec 2025 14:34:19 +0800 Subject: [PATCH 333/334] Update README_eng.md --- README_eng.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_eng.md b/README_eng.md index 7bfae4169..a55ad7ef2 100644 --- a/README_eng.md +++ b/README_eng.md @@ -244,7 +244,7 @@ Major updates of the business version 8. Built-in `XPosed Hook` framework 9. Add positioning mock code 10. Add code to change device -11. Nearly 600 other fixes and improvements +11. Nearly 700 other fixes and improvements
From d94723f17fb6a1fcb2a88845135d2a75cc9da764 Mon Sep 17 00:00:00 2001 From: xxxyanchenxxx Date: Mon, 29 Dec 2025 14:36:03 +0800 Subject: [PATCH 334/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 88d971738..a2f30d7ec 100644 --- a/README.md +++ b/README.md @@ -261,7 +261,7 @@ VirtualApp虚拟机技术归属于:山东盒一网络科技有限公司(原 648、从处理openat2与faccessat2,seccomp等调用
647、适配APP中对seccomp-bpf的调用
-646、适配某些应用因为监测打不开的问题
+646、处理某些应用因为检测打不开
**2025年12月3号 至 2025年 12月18号 商业版代码更新内容**

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%0A|@bW0wN|L zVge#2AYuX{CLm%0A|@bW0wN|LVge#2AYuX{CLm%0A|@bW0wN~=1Y+`$1i1$6s63CF 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�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