From bdef42962fb0b86f80fbd2ac8102c1569263d828 Mon Sep 17 00:00:00 2001
From: chiteroman <98092901+chiteroman@users.noreply.github.com>
Date: Wed, 7 Feb 2024 18:03:56 +0100
Subject: [PATCH] Prepare v15.7
---
.idea/vcs.xml | 7 -
app/build.gradle.kts | 27 +-
app/src/main/cpp/Android.mk | 30 -
app/src/main/cpp/Application.mk | 8 -
app/src/main/cpp/CMakeLists.txt | 13 +
app/src/main/cpp/Dobby/.clang-format | 18 +
app/src/main/cpp/Dobby/.gitignore | 80 +
app/src/main/cpp/Dobby/CMakeLists.txt | 384 +
app/src/main/cpp/Dobby/LICENSE | 201 +
app/src/main/cpp/Dobby/README.md | 26 +
app/src/main/cpp/Dobby/README_zh-cn.md | 3 +
.../MGCopyAnswerMonitor.cc | 46 +
.../dynamic_loader_monitor.cc | 94 +
.../file_operation_monitor.cc | 97 +
.../memory_operation_instrument.cc | 58 +
...posix_file_descriptor_operation_monitor.cc | 120 +
.../posix_socket_network_monitor.cc | 57 +
.../BionicLinkerUtil/bionic_linker_demo.cc | 36 +
.../BionicLinkerUtil/bionic_linker_util.cc | 197 +
.../BionicLinkerUtil/bionic_linker_util.h | 23 +
.../cpp/Dobby/builtin-plugin/CMakeLists.txt | 15 +
.../ImportTableReplace/CMakeLists.txt | 3 +
.../dobby_import_replace.cc | 192 +
.../ImportTableReplace/dobby_import_replace.h | 11 +
.../ObjcRuntimeReplace/CMakeLists.txt | 7 +
.../dobby_objc_runtime_repalce.h | 18 +
.../dobby_objc_runtime_replace.mm | 54 +
.../SupervisorCallMonitor/CMakeLists.txt | 23 +
.../SupervisorCallMonitor/README | 1 +
.../mach_system_call_log_handler.cc | 193 +
.../SupervisorCallMonitor/misc_utility.cc | 44 +
.../SupervisorCallMonitor/misc_utility.h | 28 +
.../sensitive_api_monitor.cc | 95 +
.../supervisor_call_monitor.cc | 138 +
.../supervisor_call_monitor.h | 24 +
.../system_call_log_handler.cc | 98 +
.../test_supervisor_call_monitor.cc | 16 +
.../SymbolResolver/CMakeLists.txt | 55 +
.../SymbolResolver/dobby_symbol_resolver.h | 15 +
.../elf/dobby_symbol_resolver.cc | 238 +
.../macho/dobby_symbol_resolver.cc | 114 +
.../macho/dobby_symbol_resolver_priv.h | 6 +
.../SymbolResolver/macho/macho_ctx.cc | 358 +
.../SymbolResolver/macho/macho_ctx.h | 86 +
.../macho/macho_file_symbol_resolver.cpp | 68 +
.../macho/macho_file_symbol_resolver.h | 8 +
.../macho/shared-cache/dyld_cache_format.h | 560 +
.../SymbolResolver/macho/shared_cache_ctx.cpp | 183 +
.../SymbolResolver/macho/shared_cache_ctx.h | 45 +
.../SymbolResolver/mmap_file_util.h | 63 +
.../pe/dobby_symbol_resolver.cc | 26 +
app/src/main/cpp/Dobby/cmake/Macros.cmake | 3 +
app/src/main/cpp/Dobby/cmake/Util.cmake | 29 +
.../cpp/Dobby/cmake/auto_source_group.cmake | 32 +
.../Dobby/cmake/build_environment_check.cmake | 86 +
.../cpp/Dobby/cmake/compiler_and_linker.cmake | 55 +
.../cpp/Dobby/cmake/dobby.xcode.source.cmake | 94 +
.../cmake/platform/platform-darwin.cmake | 30 +
.../Dobby/cmake/xcode_generator_helper.cmake | 9 +
app/src/main/cpp/Dobby/docs/compile.md | 89 +
.../main/cpp/Dobby/examples/CMakeLists.txt | 18 +
app/src/main/cpp/Dobby/examples/main.cc | 14 +
.../main/cpp/Dobby/examples/socket_example.cc | 212 +
.../main/cpp/Dobby/external/TINYSTL/README | 1 +
.../cpp/Dobby/external/TINYSTL/algorithm.h | 1 +
.../cpp/Dobby/external/TINYSTL/allocator.h | 49 +
.../main/cpp/Dobby/external/TINYSTL/buffer.h | 310 +
.../cpp/Dobby/external/TINYSTL/function.h | 48 +
.../main/cpp/Dobby/external/TINYSTL/hash.h | 53 +
.../cpp/Dobby/external/TINYSTL/hash_base.h | 292 +
app/src/main/cpp/Dobby/external/TINYSTL/new.h | 44 +
.../main/cpp/Dobby/external/TINYSTL/stddef.h | 43 +
.../main/cpp/Dobby/external/TINYSTL/string.h | 295 +
.../cpp/Dobby/external/TINYSTL/string_view.h | 147 +
.../main/cpp/Dobby/external/TINYSTL/traits.h | 100 +
.../Dobby/external/TINYSTL/unordered_map.h | 289 +
.../Dobby/external/TINYSTL/unordered_set.h | 265 +
.../main/cpp/Dobby/external/TINYSTL/vector.h | 353 +
.../deprecated/misc-helper/CMakeLists.txt | 18 +
.../deprecated/misc-helper/async_logger.cc | 65 +
.../misc-helper/deprecated/pthread_helper.cc | 129 +
.../misc-helper/deprecated/pthread_helper.h | 85 +
.../misc-helper/deprecated/unistd_helper.h | 30 +
.../deprecated/misc-helper/format_printer.cc | 11 +
.../misc-helper/misc-helper/async_logger.h | 8 +
.../misc-helper/misc-helper/format_printer.h | 3 +
.../misc-helper/misc-helper/variable_cache.h | 17 +
.../deprecated/misc-helper/variable_cache.c | 118 +
.../cpp/Dobby/external/logging/CMakeLists.txt | 18 +
.../cpp/Dobby/external/logging/logging.cc | 137 +
.../external/logging/logging/check_logging.h | 87 +
.../Dobby/external/logging/logging/logging.h | 202 +
.../Dobby/external/logging/logging_kern.cc | 0
.../external/logging/priv_headers/_simple.h | 162 +
.../cpp/Dobby/external/osbase/CMakeLists.txt | 3 +
app/src/main/cpp/Dobby/include/dobby.h | 152 +
app/src/main/cpp/Dobby/scripts/Dockerfile | 10 +
.../cpp/Dobby/scripts/platform_builder.py | 242 +
.../scripts/setup_linux_cross_compile.sh | 61 +
.../scripts/setup_macos_cross_compile.sh | 22 +
.../ExecMemory/clear-cache-tool-all.c | 3 +
.../ExecMemory/code-patch-tool-darwin.cc | 0
.../Darwin/ProcessRuntimeUtility.cc | 0
.../UnifiedInterface/platform-darwin.cc | 0
.../ExecMemory/clear-cache-tool-all.c | 145 +
.../clear-cache-tool-arm-dummy.cc | 53 +
.../clear-cache-tool-arm64-dummy.cc | 103 +
.../ExecMemory/code-patch-tool-darwin.cc | 172 +
.../ExecMemory/code-patch-tool-posix.cc | 37 +
.../ExecMemory/code-patch-tool-windows.cc | 27 +
.../mach_interface_support/substrated.defs | 27 +
.../MultiThreadSupport/ThreadSupport.cpp | 22 +
.../MultiThreadSupport/ThreadSupport.h | 63 +
.../Darwin/ProcessRuntimeUtility.cc | 143 +
.../Linux/ProcessRuntimeUtility.cc | 237 +
.../Windows/ProcessRuntimeUtility.cc | 81 +
.../Backend/UserMode/Thread/PlatformThread.cc | 19 +
.../Backend/UserMode/Thread/PlatformThread.h | 32 +
.../UserMode/Thread/platform-thread-posix.cc | 71 +
.../Thread/platform-thread-windows.cc | 25 +
.../platform-darwin/mach_vm.h | 933 +
.../UnifiedInterface/platform-posix.cc | 183 +
.../UnifiedInterface/platform-windows.cc | 86 +
.../UserMode/UnifiedInterface/semaphore.cc | 160 +
.../UserMode/UnifiedInterface/semaphore.h | 98 +
.../InstructionRelocation.h | 5 +
.../arm/InstructionRelocationARM.cc | 895 +
.../arm/InstructionRelocationARM.h | 307 +
.../arm64/InstructionRelocationARM64.cc | 366 +
.../arm64/InstructionRelocationARM64.h | 13 +
.../arm64/inst_constants.h | 49 +
.../arm64/inst_decode_encode_kit.h | 110 +
.../x64/InstructionRelocationX64.cc | 79 +
.../x64/InstructionRelocationX64.h | 9 +
.../x86/InstructionRelocationX86.cc | 80 +
.../x86/InstructionRelocationX86.h | 9 +
.../x86/InstructionRelocationX86Shared.cc | 218 +
.../x86/InstructionRelocationX86Shared.h | 16 +
.../InstructionRelocation/x86/X86DecodeKit.h | 21 +
.../x86/deprecated/Ia32Disassembler.cc | 388 +
.../x86/deprecated/X86OpcodoDecodeTable.cc | 604 +
.../x86/deprecated/X86OpcodoDecodeTable.h | 142 +
.../x86/x86_insn_decode/build_config.h | 144 +
.../x86/x86_insn_decode/x86_insn_decode.c | 564 +
.../x86/x86_insn_decode/x86_insn_decode.h | 200 +
.../x86/x86_insn_decode/x86_insn_reader.c | 87 +
.../x86_opcode_modrm_reg_group.c | 218 +
.../x86/x86_insn_decode/x86_opcode_one_byte.c | 215 +
.../x86_insn_decode/x86_opcode_sse_group.c | 545 +
.../x86/x86_insn_decode/x86_opcode_two_byte.c | 249 +
.../main/cpp/Dobby/source/InterceptEntry.cpp | 16 +
.../main/cpp/Dobby/source/InterceptEntry.h | 30 +
.../InterceptRouting/InterceptRouting.cpp | 97 +
.../InterceptRouting/InterceptRouting.h | 62 +
.../FunctionInlineHook/FunctionInlineHook.cc | 52 +
.../FunctionInlineHookRouting.h | 22 +
.../Routing/FunctionInlineHook/RoutingImpl.cc | 22 +
.../FunctionWrapper/FunctionWrapperExport.cc | 27 +
.../FunctionWrapper/function-wrapper.cc | 38 +
.../FunctionWrapper/function-wrapper.h | 40 +
.../intercept_routing_handler.cc | 79 +
.../intercept_routing_handler.h | 27 +
.../InstructionInstrument.cc | 42 +
.../InstructionInstrumentRouting.h | 30 +
.../InstructionInstrument/RoutingImpl.cc | 40 +
.../instrument_routing_handler.cc | 21 +
.../instrument_routing_handler.h | 7 +
.../NearBranchTrampoline.cc | 50 +
.../NearBranchTrampoline.h | 15 +
.../near_trampoline_arm64.cc | 81 +
.../RoutingPlugin/RoutingPlugin.cc | 11 +
.../RoutingPlugin/RoutingPlugin.h | 30 +
app/src/main/cpp/Dobby/source/Interceptor.cpp | 40 +
app/src/main/cpp/Dobby/source/Interceptor.h | 25 +
.../MemoryAllocator/AssemblyCodeBuilder.cc | 34 +
.../MemoryAllocator/AssemblyCodeBuilder.h | 14 +
.../CodeBuffer/CodeBufferBase.cc | 53 +
.../CodeBuffer/CodeBufferBase.h | 40 +
.../CodeBuffer/code-buffer-arm.h | 59 +
.../CodeBuffer/code-buffer-arm64.h | 24 +
.../CodeBuffer/code-buffer-x64.h | 17 +
.../CodeBuffer/code-buffer-x86.cc | 18 +
.../CodeBuffer/code-buffer-x86.h | 12 +
.../CodeBuffer/code_buffer_arm.h | 56 +
.../CodeBuffer/code_buffer_arm64.h | 21 +
.../CodeBuffer/code_buffer_x64.h | 14 +
.../CodeBuffer/code_buffer_x86.h | 14 +
.../source/MemoryAllocator/MemoryAllocator.cc | 106 +
.../MemoryAllocator/NearMemoryAllocator.cc | 235 +
.../MemoryAllocator/NearMemoryAllocator.h | 30 +
.../ExecMemory/ClearCacheTool.h | 11 +
.../ExecMemory/CodePatchTool.h | 3 +
.../MemoryAllocator.h | 101 +
.../PlatformUnifiedInterface/platform.h | 82 +
.../PlatformUtil/ProcessRuntimeUtility.h | 26 +
.../ClosureTrampoline.h | 39 +
.../arm/ClosureTrampolineARM.cc | 49 +
.../arm/closure_bridge_arm.cc | 90 +
.../arm/dummy/closure-bridge-template-arm.cc | 65 +
.../dummy/closure-trampoline-template-arm.S | 34 +
.../ClosureTrampolineBridge/arm/helper_arm.cc | 13 +
.../arm64/ClosureTrampolineARM64.cc | 63 +
.../arm64/closure_bridge_arm64.cc | 159 +
.../dummy/closure-bridge-template-arm64.c | 103 +
.../dummy/closure-trampoline-template-arm64.S | 36 +
...ynamic-closure-trampoline-template-arm64.S | 33 +
.../arm64/helper_arm64.cc | 17 +
.../common_bridge_handler.cc | 22 +
.../common_bridge_handler.h | 17 +
.../x64/ClosureTrampolineX64.cc | 45 +
.../x64/closure_bridge_x64.cc | 141 +
.../x64/dummy/closure-bridge-template-x64.c | 70 +
.../dummy/closure-trampoline-template-x64.S | 17 +
.../ClosureTrampolineBridge/x64/helper_x64.cc | 17 +
.../x86/ClosureTrampolineX86.cc | 44 +
.../x86/closure_bridge_x86.cc | 112 +
.../ClosureTrampolineBridge/x86/helper_x86.cc | 16 +
.../TrampolineBridge/Trampoline/Trampoline.h | 5 +
.../Trampoline/arm/trampoline_arm.cc | 62 +
.../Trampoline/arm64/trampoline_arm64.cc | 41 +
.../Trampoline/x64/trampoline_x64.cc | 54 +
.../Trampoline/x86/trampoline_x86.cc | 33 +
.../main/cpp/Dobby/source/core/arch/Cpu.cc | 5 +
app/src/main/cpp/Dobby/source/core/arch/Cpu.h | 7 +
.../cpp/Dobby/source/core/arch/CpuFeature.cc | 7 +
.../cpp/Dobby/source/core/arch/CpuFeature.h | 19 +
.../cpp/Dobby/source/core/arch/CpuRegister.cc | 10 +
.../cpp/Dobby/source/core/arch/CpuRegister.h | 25 +
.../cpp/Dobby/source/core/arch/CpuUtils.h | 17 +
.../source/core/arch/arm/constants-arm.h | 70 +
.../source/core/arch/arm/registers-arm.h | 58 +
.../source/core/arch/arm64/constants-arm64.h | 387 +
.../source/core/arch/arm64/registers-arm64.h | 142 +
.../source/core/arch/x64/constants-x64.h | 21 +
.../source/core/arch/x64/registers-x64.h | 244 +
.../source/core/arch/x86/constants-x86.h | 19 +
.../cpp/Dobby/source/core/arch/x86/cpu-x86.cc | 10 +
.../cpp/Dobby/source/core/arch/x86/cpu-x86.h | 120 +
.../source/core/arch/x86/registers-x86.h | 124 +
.../core/assembler/AssemblerPseudoLabel.h | 85 +
.../source/core/assembler/assembler-arch.h | 28 +
.../source/core/assembler/assembler-arm.cc | 41 +
.../source/core/assembler/assembler-arm.h | 354 +
.../source/core/assembler/assembler-arm64.cc | 25 +
.../source/core/assembler/assembler-arm64.h | 560 +
.../source/core/assembler/assembler-ia32.cc | 34 +
.../source/core/assembler/assembler-ia32.h | 456 +
.../source/core/assembler/assembler-x64.cc | 34 +
.../source/core/assembler/assembler-x64.h | 596 +
.../core/assembler/assembler-x86-shared.cc | 17 +
.../core/assembler/assembler-x86-shared.h | 707 +
.../Dobby/source/core/assembler/assembler.cc | 64 +
.../Dobby/source/core/assembler/assembler.h | 74 +
.../Dobby/source/core/codegen/codegen-arm.cc | 19 +
.../Dobby/source/core/codegen/codegen-arm.h | 22 +
.../source/core/codegen/codegen-arm64.cc | 26 +
.../Dobby/source/core/codegen/codegen-arm64.h | 21 +
.../Dobby/source/core/codegen/codegen-ia32.cc | 23 +
.../Dobby/source/core/codegen/codegen-ia32.h | 22 +
.../Dobby/source/core/codegen/codegen-x64.cc | 25 +
.../Dobby/source/core/codegen/codegen-x64.h | 22 +
.../cpp/Dobby/source/core/codegen/codegen.h | 17 +
.../cpp/Dobby/source/core/emulator/dummy.cc | 0
app/src/main/cpp/Dobby/source/dobby.cpp | 31 +
app/src/main/cpp/Dobby/source/dobby/common.h | 11 +
.../cpp/Dobby/source/dobby/dobby_internal.h | 13 +
.../Dobby/source/dobby/kernel_mode_header.h | 6 +
app/src/main/cpp/Dobby/source/dobby/pac_kit.h | 35 +
.../source/dobby/platform_detect_macro.h | 15 +
.../Dobby/source/dobby/platform_features.h | 50 +
app/src/main/cpp/Dobby/source/dobby/types.h | 10 +
.../cpp/Dobby/source/dobby/utility_macro.h | 62 +
app/src/main/cpp/Dobby/tests/CMakeLists.txt | 120 +
.../main/cpp/Dobby/tests/UniconEmulator.cpp | 219 +
app/src/main/cpp/Dobby/tests/UniconEmulator.h | 73 +
.../cpp/Dobby/tests/test_insn_decoder_x86.cpp | 267 +
.../cpp/Dobby/tests/test_insn_relo_arm.cpp | 116 +
.../cpp/Dobby/tests/test_insn_relo_arm64.cpp | 97 +
.../cpp/Dobby/tests/test_insn_relo_x64.cpp | 38 +
app/src/main/cpp/Dobby/tests/test_native.cpp | 30 +
app/src/main/cpp/cJSON/cJSON.c | 3129 --
app/src/main/cpp/cJSON/cJSON.h | 300 -
app/src/main/cpp/json.hpp | 24765 ++++++++++++++++
app/src/main/cpp/main.cpp | 129 +-
app/src/main/cpp/shadowhook/arch/arm/sh_a32.c | 446 -
app/src/main/cpp/shadowhook/arch/arm/sh_a32.h | 41 -
.../main/cpp/shadowhook/arch/arm/sh_inst.c | 523 -
.../main/cpp/shadowhook/arch/arm/sh_inst.h | 41 -
app/src/main/cpp/shadowhook/arch/arm/sh_t16.c | 284 -
app/src/main/cpp/shadowhook/arch/arm/sh_t16.h | 46 -
app/src/main/cpp/shadowhook/arch/arm/sh_t32.c | 408 -
app/src/main/cpp/shadowhook/arch/arm/sh_t32.h | 36 -
app/src/main/cpp/shadowhook/arch/arm/sh_txx.c | 60 -
app/src/main/cpp/shadowhook/arch/arm/sh_txx.h | 39 -
.../main/cpp/shadowhook/arch/arm64/sh_a64.c | 310 -
.../main/cpp/shadowhook/arch/arm64/sh_a64.h | 44 -
.../main/cpp/shadowhook/arch/arm64/sh_inst.c | 203 -
.../main/cpp/shadowhook/arch/arm64/sh_inst.h | 42 -
app/src/main/cpp/shadowhook/common/bytesig.c | 291 -
app/src/main/cpp/shadowhook/common/bytesig.h | 157 -
.../main/cpp/shadowhook/common/sh_config.h | 55 -
app/src/main/cpp/shadowhook/common/sh_errno.c | 107 -
app/src/main/cpp/shadowhook/common/sh_errno.h | 40 -
app/src/main/cpp/shadowhook/common/sh_log.c | 53 -
app/src/main/cpp/shadowhook/common/sh_log.h | 70 -
app/src/main/cpp/shadowhook/common/sh_sig.h | 49 -
.../main/cpp/shadowhook/common/sh_trampo.c | 172 -
.../main/cpp/shadowhook/common/sh_trampo.h | 52 -
app/src/main/cpp/shadowhook/common/sh_util.c | 538 -
app/src/main/cpp/shadowhook/common/sh_util.h | 103 -
.../main/cpp/shadowhook/include/shadowhook.h | 191 -
app/src/main/cpp/shadowhook/sh_enter.c | 47 -
app/src/main/cpp/shadowhook/sh_enter.h | 30 -
app/src/main/cpp/shadowhook/sh_exit.c | 420 -
app/src/main/cpp/shadowhook/sh_exit.h | 34 -
app/src/main/cpp/shadowhook/sh_hub.c | 538 -
app/src/main/cpp/shadowhook/sh_hub.h | 45 -
app/src/main/cpp/shadowhook/sh_jni.c | 139 -
app/src/main/cpp/shadowhook/sh_linker.c | 412 -
app/src/main/cpp/shadowhook/sh_linker.h | 41 -
app/src/main/cpp/shadowhook/sh_recorder.c | 517 -
app/src/main/cpp/shadowhook/sh_recorder.h | 37 -
app/src/main/cpp/shadowhook/sh_safe.c | 133 -
app/src/main/cpp/shadowhook/sh_safe.h | 37 -
app/src/main/cpp/shadowhook/sh_switch.c | 343 -
app/src/main/cpp/shadowhook/sh_switch.h | 34 -
app/src/main/cpp/shadowhook/sh_task.c | 333 -
app/src/main/cpp/shadowhook/sh_task.h | 40 -
app/src/main/cpp/shadowhook/shadowhook.c | 328 -
.../cpp/shadowhook/third_party/bsd/queue.h | 551 -
.../cpp/shadowhook/third_party/bsd/tree.h | 759 -
.../cpp/shadowhook/third_party/lss/LICENSE | 28 -
.../third_party/lss/linux_syscall_support.h | 4867 ---
.../cpp/shadowhook/third_party/xdl/LICENSE | 21 -
.../main/cpp/shadowhook/third_party/xdl/xdl.c | 916 -
.../main/cpp/shadowhook/third_party/xdl/xdl.h | 92 -
.../shadowhook/third_party/xdl/xdl_iterate.c | 297 -
.../shadowhook/third_party/xdl/xdl_iterate.h | 43 -
.../shadowhook/third_party/xdl/xdl_linker.c | 234 -
.../shadowhook/third_party/xdl/xdl_linker.h | 40 -
.../cpp/shadowhook/third_party/xdl/xdl_lzma.c | 187 -
.../cpp/shadowhook/third_party/xdl/xdl_lzma.h | 40 -
.../cpp/shadowhook/third_party/xdl/xdl_util.c | 95 -
.../cpp/shadowhook/third_party/xdl/xdl_util.h | 71 -
.../playintegrityfix/CustomKeyStoreSpi.java | 105 -
.../playintegrityfix/CustomProvider.java | 13 +-
.../playintegrityfix/EntryPoint.java | 39 +-
module/module.prop | 4 +-
module/post-fs-data.sh | 10 +
module/service.sh | 5 -
350 files changed, 50901 insertions(+), 19873 deletions(-)
delete mode 100644 .idea/vcs.xml
delete mode 100644 app/src/main/cpp/Android.mk
delete mode 100644 app/src/main/cpp/Application.mk
create mode 100644 app/src/main/cpp/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/.clang-format
create mode 100644 app/src/main/cpp/Dobby/.gitignore
create mode 100644 app/src/main/cpp/Dobby/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/LICENSE
create mode 100644 app/src/main/cpp/Dobby/README.md
create mode 100644 app/src/main/cpp/Dobby/README_zh-cn.md
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/MGCopyAnswerMonitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/dynamic_loader_monitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/file_operation_monitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/memory_operation_instrument.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_file_descriptor_operation_monitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_socket_network_monitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_demo.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_repalce.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_replace.mm
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/README
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/mach_system_call_log_handler.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/sensitive_api_monitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/system_call_log_handler.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/test_supervisor_call_monitor.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/dobby_symbol_resolver.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/elf/dobby_symbol_resolver.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver_priv.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.cc
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.cpp
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared-cache/dyld_cache_format.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.cpp
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/mmap_file_util.h
create mode 100644 app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/pe/dobby_symbol_resolver.cc
create mode 100644 app/src/main/cpp/Dobby/cmake/Macros.cmake
create mode 100644 app/src/main/cpp/Dobby/cmake/Util.cmake
create mode 100644 app/src/main/cpp/Dobby/cmake/auto_source_group.cmake
create mode 100644 app/src/main/cpp/Dobby/cmake/build_environment_check.cmake
create mode 100644 app/src/main/cpp/Dobby/cmake/compiler_and_linker.cmake
create mode 100644 app/src/main/cpp/Dobby/cmake/dobby.xcode.source.cmake
create mode 100644 app/src/main/cpp/Dobby/cmake/platform/platform-darwin.cmake
create mode 100644 app/src/main/cpp/Dobby/cmake/xcode_generator_helper.cmake
create mode 100644 app/src/main/cpp/Dobby/docs/compile.md
create mode 100644 app/src/main/cpp/Dobby/examples/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/examples/main.cc
create mode 100644 app/src/main/cpp/Dobby/examples/socket_example.cc
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/README
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/algorithm.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/allocator.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/buffer.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/function.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/hash.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/hash_base.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/new.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/stddef.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/string.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/string_view.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/traits.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/unordered_map.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/unordered_set.h
create mode 100644 app/src/main/cpp/Dobby/external/TINYSTL/vector.h
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/async_logger.cc
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.cc
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/pthread_helper.h
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/deprecated/unistd_helper.h
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/format_printer.cc
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/async_logger.h
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/format_printer.h
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/misc-helper/variable_cache.h
create mode 100644 app/src/main/cpp/Dobby/external/deprecated/misc-helper/variable_cache.c
create mode 100644 app/src/main/cpp/Dobby/external/logging/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/external/logging/logging.cc
create mode 100644 app/src/main/cpp/Dobby/external/logging/logging/check_logging.h
create mode 100644 app/src/main/cpp/Dobby/external/logging/logging/logging.h
create mode 100644 app/src/main/cpp/Dobby/external/logging/logging_kern.cc
create mode 100644 app/src/main/cpp/Dobby/external/logging/priv_headers/_simple.h
create mode 100644 app/src/main/cpp/Dobby/external/osbase/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/include/dobby.h
create mode 100644 app/src/main/cpp/Dobby/scripts/Dockerfile
create mode 100644 app/src/main/cpp/Dobby/scripts/platform_builder.py
create mode 100644 app/src/main/cpp/Dobby/scripts/setup_linux_cross_compile.sh
create mode 100644 app/src/main/cpp/Dobby/scripts/setup_macos_cross_compile.sh
create mode 100644 app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/clear-cache-tool-all.c
create mode 100644 app/src/main/cpp/Dobby/source/Backend/KernelMode/ExecMemory/code-patch-tool-darwin.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/KernelMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/KernelMode/UnifiedInterface/platform-darwin.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm-dummy.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/clear-cache-tool/clear-cache-tool-arm64-dummy.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-darwin.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-posix.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/code-patch-tool-windows.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/ExecMemory/substrated/mach_interface_support/substrated.defs
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.cpp
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/MultiThreadSupport/ThreadSupport.h
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/PlatformThread.h
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-posix.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/Thread/platform-thread-windows.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-darwin/mach_vm.h
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-posix.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/platform-windows.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.cc
create mode 100644 app/src/main/cpp/Dobby/source/Backend/UserMode/UnifiedInterface/semaphore.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/InstructionRelocation.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.cc
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/arm/InstructionRelocationARM.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.cc
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/InstructionRelocationARM64.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_constants.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/arm64/inst_decode_encode_kit.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.cc
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x64/InstructionRelocationX64.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.cc
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.cc
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/InstructionRelocationX86Shared.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/X86DecodeKit.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/Ia32Disassembler.cc
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.cc
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/deprecated/X86OpcodoDecodeTable.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/build_config.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.h
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_insn_reader.c
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_modrm_reg_group.c
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_one_byte.c
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_sse_group.c
create mode 100644 app/src/main/cpp/Dobby/source/InstructionRelocation/x86/x86_insn_decode/x86_opcode_two_byte.c
create mode 100644 app/src/main/cpp/Dobby/source/InterceptEntry.cpp
create mode 100644 app/src/main/cpp/Dobby/source/InterceptEntry.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.cpp
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/InterceptRouting.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHook.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHookRouting.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionInlineHook/RoutingImpl.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/FunctionWrapperExport.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/function-wrapper.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/FunctionWrapper/intercept_routing_handler.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrument.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrumentRouting.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/RoutingImpl.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.h
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/near_trampoline_arm64.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc
create mode 100644 app/src/main/cpp/Dobby/source/InterceptRouting/RoutingPlugin/RoutingPlugin.h
create mode 100644 app/src/main/cpp/Dobby/source/Interceptor.cpp
create mode 100644 app/src/main/cpp/Dobby/source/Interceptor.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.cc
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/AssemblyCodeBuilder.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/CodeBufferBase.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-arm64.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x64.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.cc
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code-buffer-x86.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_arm64.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x64.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/CodeBuffer/code_buffer_x86.h
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/MemoryAllocator.cc
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.cc
create mode 100644 app/src/main/cpp/Dobby/source/MemoryAllocator/NearMemoryAllocator.h
create mode 100644 app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/ClearCacheTool.h
create mode 100644 app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/ExecMemory/CodePatchTool.h
create mode 100644 app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/MemoryAllocator.h
create mode 100644 app/src/main/cpp/Dobby/source/PlatformUnifiedInterface/platform.h
create mode 100644 app/src/main/cpp/Dobby/source/PlatformUtil/ProcessRuntimeUtility.h
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/ClosureTrampoline.h
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/closure_bridge_arm.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-bridge-template-arm.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/dummy/closure-trampoline-template-arm.S
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm/helper_arm.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure_bridge_arm64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-bridge-template-arm64.c
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/closure-trampoline-template-arm64.S
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/dummy/dynamic-closure-trampoline-template-arm64.S
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper_arm64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.h
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/closure_bridge_x64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-bridge-template-x64.c
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/dummy/closure-trampoline-template-x64.S
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x64/helper_x64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/ClosureTrampolineX86.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/closure_bridge_x86.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/ClosureTrampolineBridge/x86/helper_x86.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/Trampoline.h
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm/trampoline_arm.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/arm64/trampoline_arm64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x64/trampoline_x64.cc
create mode 100644 app/src/main/cpp/Dobby/source/TrampolineBridge/Trampoline/x86/trampoline_x86.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/Cpu.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/Cpu.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/CpuFeature.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/CpuFeature.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/CpuRegister.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/CpuRegister.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/CpuUtils.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/arm/constants-arm.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/arm/registers-arm.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/arm64/constants-arm64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/arm64/registers-arm64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/x64/constants-x64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/x64/registers-x64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/x86/constants-x86.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/x86/cpu-x86.h
create mode 100644 app/src/main/cpp/Dobby/source/core/arch/x86/registers-x86.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/AssemblerPseudoLabel.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-arch.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-arm.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-arm64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-ia32.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-x64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler-x86-shared.h
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/assembler/assembler.h
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-arm.h
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-arm64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-ia32.h
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.cc
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen-x64.h
create mode 100644 app/src/main/cpp/Dobby/source/core/codegen/codegen.h
create mode 100644 app/src/main/cpp/Dobby/source/core/emulator/dummy.cc
create mode 100644 app/src/main/cpp/Dobby/source/dobby.cpp
create mode 100644 app/src/main/cpp/Dobby/source/dobby/common.h
create mode 100644 app/src/main/cpp/Dobby/source/dobby/dobby_internal.h
create mode 100644 app/src/main/cpp/Dobby/source/dobby/kernel_mode_header.h
create mode 100644 app/src/main/cpp/Dobby/source/dobby/pac_kit.h
create mode 100644 app/src/main/cpp/Dobby/source/dobby/platform_detect_macro.h
create mode 100644 app/src/main/cpp/Dobby/source/dobby/platform_features.h
create mode 100644 app/src/main/cpp/Dobby/source/dobby/types.h
create mode 100644 app/src/main/cpp/Dobby/source/dobby/utility_macro.h
create mode 100644 app/src/main/cpp/Dobby/tests/CMakeLists.txt
create mode 100644 app/src/main/cpp/Dobby/tests/UniconEmulator.cpp
create mode 100644 app/src/main/cpp/Dobby/tests/UniconEmulator.h
create mode 100644 app/src/main/cpp/Dobby/tests/test_insn_decoder_x86.cpp
create mode 100644 app/src/main/cpp/Dobby/tests/test_insn_relo_arm.cpp
create mode 100644 app/src/main/cpp/Dobby/tests/test_insn_relo_arm64.cpp
create mode 100644 app/src/main/cpp/Dobby/tests/test_insn_relo_x64.cpp
create mode 100644 app/src/main/cpp/Dobby/tests/test_native.cpp
delete mode 100644 app/src/main/cpp/cJSON/cJSON.c
delete mode 100644 app/src/main/cpp/cJSON/cJSON.h
create mode 100644 app/src/main/cpp/json.hpp
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_a32.c
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_a32.h
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_inst.c
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_inst.h
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_t16.c
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_t16.h
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_t32.c
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_t32.h
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_txx.c
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm/sh_txx.h
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm64/sh_a64.c
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm64/sh_a64.h
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm64/sh_inst.c
delete mode 100644 app/src/main/cpp/shadowhook/arch/arm64/sh_inst.h
delete mode 100644 app/src/main/cpp/shadowhook/common/bytesig.c
delete mode 100644 app/src/main/cpp/shadowhook/common/bytesig.h
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_config.h
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_errno.c
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_errno.h
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_log.c
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_log.h
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_sig.h
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_trampo.c
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_trampo.h
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_util.c
delete mode 100644 app/src/main/cpp/shadowhook/common/sh_util.h
delete mode 100644 app/src/main/cpp/shadowhook/include/shadowhook.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_enter.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_enter.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_exit.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_exit.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_hub.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_hub.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_jni.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_linker.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_linker.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_recorder.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_recorder.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_safe.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_safe.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_switch.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_switch.h
delete mode 100644 app/src/main/cpp/shadowhook/sh_task.c
delete mode 100644 app/src/main/cpp/shadowhook/sh_task.h
delete mode 100644 app/src/main/cpp/shadowhook/shadowhook.c
delete mode 100644 app/src/main/cpp/shadowhook/third_party/bsd/queue.h
delete mode 100644 app/src/main/cpp/shadowhook/third_party/bsd/tree.h
delete mode 100644 app/src/main/cpp/shadowhook/third_party/lss/LICENSE
delete mode 100644 app/src/main/cpp/shadowhook/third_party/lss/linux_syscall_support.h
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/LICENSE
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl.c
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl.h
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_iterate.c
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_iterate.h
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_linker.c
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_linker.h
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_lzma.c
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_lzma.h
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_util.c
delete mode 100644 app/src/main/cpp/shadowhook/third_party/xdl/xdl_util.h
delete mode 100644 app/src/main/java/es/chiteroman/playintegrityfix/CustomKeyStoreSpi.java
create mode 100644 module/post-fs-data.sh
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 6680155..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index ef9ac2a..4b64b1e 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -12,8 +12,8 @@ android {
applicationId = "es.chiteroman.playintegrityfix"
minSdk = 26
targetSdk = 34
- versionCode = 15600
- versionName = "v15.6"
+ versionCode = 15700
+ versionName = "v15.7"
multiDexEnabled = false
buildFeatures {
@@ -24,16 +24,20 @@ android {
jniLibs {
excludes += "**/liblog.so"
excludes += "**/libdobby.so"
- excludes += "**/libshadowhook.so"
}
}
externalNativeBuild {
- ndk {
- abiFilters += "arm64-v8a"
- abiFilters += "armeabi-v7a"
+ cmake {
+ arguments += "-DANDROID_STL=none"
+ arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"
+ arguments += "-DPlugin.Android.BionicLinkerUtil=ON"
- jobs = Runtime.getRuntime().availableProcessors()
+ cppFlags += "-std=c++20"
+ cppFlags += "-fno-exceptions"
+ cppFlags += "-fno-rtti"
+ cppFlags += "-fvisibility=hidden"
+ cppFlags += "-fvisibility-inlines-hidden"
}
}
}
@@ -53,12 +57,17 @@ android {
}
externalNativeBuild {
- ndkBuild {
- path = file("src/main/cpp/Android.mk")
+ cmake {
+ path = file("src/main/cpp/CMakeLists.txt")
+ version = "3.22.1"
}
}
}
+dependencies {
+ implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0")
+}
+
tasks.register("updateModuleProp") {
doLast {
val versionName = project.android.defaultConfig.versionName
diff --git a/app/src/main/cpp/Android.mk b/app/src/main/cpp/Android.mk
deleted file mode 100644
index 1f5bda8..0000000
--- a/app/src/main/cpp/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := playintegrityfix
-LOCAL_SRC_FILES := $(LOCAL_PATH)/main.cpp
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
-
-LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/cJSON/cJSON.c)
-LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/*.c)
-LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/common/*.c)
-LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/third_party/xdl/*.c)
-
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/cJSON
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/common
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/bsd
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/lss
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/xdl
-
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
- LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/arch/arm/*.c)
- LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/arch/arm
-else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
- LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/arch/arm64/*.c)
- LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/arch/arm64
-endif
-
-LOCAL_LDLIBS := -llog
-include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/app/src/main/cpp/Application.mk b/app/src/main/cpp/Application.mk
deleted file mode 100644
index 6160a2d..0000000
--- a/app/src/main/cpp/Application.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-APP_STL := system
-APP_ABI := armeabi-v7a arm64-v8a
-APP_CFLAGS := -Oz -flto -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-protector
-APP_CPPFLAGS := -std=c++2b -fno-exceptions -fno-rtti
-APP_CONLYFLAGS := -std=c2x
-APP_LDFLAGS := -Oz -flto -Wl,--exclude-libs,ALL -Wl,--gc-sections
-APP_PLATFORM := android-26
-APP_THIN_ARCHIVE := true
\ No newline at end of file
diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt
new file mode 100644
index 0000000..6c6492c
--- /dev/null
+++ b/app/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.22.1)
+
+project(playintegrityfix)
+
+find_package(cxx REQUIRED CONFIG)
+
+link_libraries(cxx::cxx)
+
+add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp)
+
+add_subdirectory(Dobby)
+
+target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC log dobby_static)
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/.clang-format b/app/src/main/cpp/Dobby/.clang-format
new file mode 100644
index 0000000..17d6bc4
--- /dev/null
+++ b/app/src/main/cpp/Dobby/.clang-format
@@ -0,0 +1,18 @@
+BasedOnStyle: LLVM
+
+IndentWidth: 2
+TabWidth: 2
+UseTab: Never
+ColumnLimit: 120
+
+FixNamespaceComments: true
+
+# default is false
+#AlignConsecutiveMacros: true
+#AlignConsecutiveAssignments: true
+#AlignConsecutiveDeclarations: true
+
+# default is true
+ReflowComments: false
+SortIncludes : false
+AllowShortFunctionsOnASingleLine: false
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/.gitignore b/app/src/main/cpp/Dobby/.gitignore
new file mode 100644
index 0000000..4bbed76
--- /dev/null
+++ b/app/src/main/cpp/Dobby/.gitignore
@@ -0,0 +1,80 @@
+.DS_Store
+.idea/
+*-build*/
+build-output/
+
+CMakeLists.txt.user
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+_deps
+
+## Build generated
+build/
+DerivedData/
+
+## Various settings
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata/
+
+## Other
+*.moved-aside
+*.xccheckout
+*.xcscmblueprint
+
+## Obj-C/Swift specific
+*.hmap
+*.ipa
+*.dSYM.zip
+*.dSYM
+
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# Prefab
+/prefab/**/*.a
+/prefab/**/*.h
+/AndroidManifest.xml
diff --git a/app/src/main/cpp/Dobby/CMakeLists.txt b/app/src/main/cpp/Dobby/CMakeLists.txt
new file mode 100644
index 0000000..6907a14
--- /dev/null
+++ b/app/src/main/cpp/Dobby/CMakeLists.txt
@@ -0,0 +1,384 @@
+cmake_minimum_required(VERSION 3.5)
+project(Dobby)
+enable_language(ASM)
+
+include(cmake/Util.cmake)
+include(cmake/Macros.cmake)
+include(cmake/build_environment_check.cmake)
+include(cmake/auto_source_group.cmake)
+include(cmake/xcode_generator_helper.cmake)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_C_STANDARD 11)
+
+auto_source_group("." "auto-source-group" "\\.(cc|cpp|c|h)$")
+
+# --- options
+
+option(DOBBY_DEBUG "Enable debug logging" OFF)
+
+option(NearBranch "Enable near branch trampoline" ON)
+
+option(FullFloatingPointRegisterPack "Save and pack all floating-point registers" OFF)
+
+option(Plugin.SymbolResolver "Enable symbol resolver" ON)
+
+option(Plugin.ImportTableReplace "Enable import table replace " OFF)
+
+option(Plugin.Android.BionicLinkerUtil "Enable android bionic linker util" OFF)
+
+option(DOBBY_BUILD_EXAMPLE "Build example" OFF)
+
+option(DOBBY_BUILD_TEST "Build test" OFF)
+
+# --- private
+option(DOBBY_BUILD_KERNEL_MODE "Build xnu kernel mode" OFF)
+
+option(Private.Obfuscation "Enable llvm obfuscation" OFF)
+
+if ((NOT DEFINED CMAKE_BUILD_TYPE) OR (CMAKE_BUILD_TYPE STREQUAL "Debug"))
+ set(DOBBY_DEBUG ON)
+endif ()
+
+
+set(compile_definitions "")
+
+# for arm64, allow access q8 - q31
+if (FullFloatingPointRegisterPack)
+ set(compile_definitions "${compile_definitions} -DFULL_FLOATING_POINT_REGISTER_PACK")
+endif ()
+
+if (DOBBY_BUILD_KERNEL_MODE)
+ set(compile_definitions "${compile_definitions} -DBUILDING_KERNEL")
+endif ()
+
+if (DOBBY_DEBUG)
+ set(compile_definitions "${compile_definitions} -DDOBBY_DEBUG")
+else ()
+ set(compile_definitions "${compile_definitions} -DDOBBY_LOGGING_DISABLE")
+endif ()
+
+if (CMAKE_GENERATOR STREQUAL Xcode)
+endif ()
+
+include(cmake/compiler_and_linker.cmake)
+
+message(STATUS "[Dobby] CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
+message(STATUS "[Dobby] DOBBY_DEBUG: ${DOBBY_DEBUG}")
+message(STATUS "[Dobby] NearBranch: ${NearBranch}")
+message(STATUS "[Dobby] FullFloatingPointRegisterPack: ${FullFloatingPointRegisterPack}")
+message(STATUS "[Dobby] Plugin.SymbolResolver: ${Plugin.SymbolResolver}")
+message(STATUS "[Dobby] Plugin.ImportTableReplace: ${Plugin.ImportTableReplace}")
+message(STATUS "[Dobby] Plugin.Android.BionicLinkerUtil: ${Plugin.Android.BionicLinkerUtil}")
+message(STATUS "[Dobby] DOBBY_BUILD_EXAMPLE: ${DOBBY_BUILD_EXAMPLE}")
+message(STATUS "[Dobby] DOBBY_BUILD_TEST: ${DOBBY_BUILD_TEST}")
+message(STATUS "[Dobby] DOBBY_BUILD_KERNEL_MODE: ${DOBBY_BUILD_KERNEL_MODE}")
+message(STATUS "[Dobby] Private.Obfuscation: ${Private.Obfuscation}")
+
+# ---
+
+include_directories(
+ .
+ ./include
+ ./source
+ source/dobby
+
+ ./external
+ ./external/logging
+
+ ./builtin-plugin
+)
+
+if (SYSTEM.Darwin AND (NOT DOBBY_BUILD_KERNEL_MODE))
+ include_directories(
+ source/Backend/UserMode
+ )
+endif ()
+
+# ---
+
+set(DOBBY_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ # cpu
+ source/core/arch/CpuFeature.cc
+ source/core/arch/CpuRegister.cc
+
+ # assembler
+ source/core/assembler/assembler.cc
+ source/core/assembler/assembler-arm.cc
+ source/core/assembler/assembler-arm64.cc
+ source/core/assembler/assembler-ia32.cc
+ source/core/assembler/assembler-x64.cc
+
+ # codegen
+ source/core/codegen/codegen-arm.cc
+ source/core/codegen/codegen-arm64.cc
+ source/core/codegen/codegen-ia32.cc
+ source/core/codegen/codegen-x64.cc
+
+ # memory kit
+ source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc
+ source/MemoryAllocator/AssemblyCodeBuilder.cc
+ source/MemoryAllocator/MemoryAllocator.cc
+
+ # instruction relocation
+ source/InstructionRelocation/arm/InstructionRelocationARM.cc
+ source/InstructionRelocation/arm64/InstructionRelocationARM64.cc
+ source/InstructionRelocation/x86/InstructionRelocationX86.cc
+ source/InstructionRelocation/x86/InstructionRelocationX86Shared.cc
+ source/InstructionRelocation/x64/InstructionRelocationX64.cc
+ source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c
+
+ # intercept routing
+ source/InterceptRouting/InterceptRouting.cpp
+
+ # intercept routing trampoline
+ source/TrampolineBridge/Trampoline/arm/trampoline_arm.cc
+ source/TrampolineBridge/Trampoline/arm64/trampoline_arm64.cc
+ source/TrampolineBridge/Trampoline/x86/trampoline_x86.cc
+ source/TrampolineBridge/Trampoline/x64/trampoline_x64.cc
+
+ # closure trampoline bridge - arm
+ source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm/helper_arm.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm/closure_bridge_arm.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc
+ # closure trampoline bridge - arm64
+ source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper_arm64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure_bridge_arm64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc
+ # closure trampoline bridge - x86
+ source/TrampolineBridge/ClosureTrampolineBridge/x86/helper_x86.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/x86/closure_bridge_x86.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/x86/ClosureTrampolineX86.cc
+ # closure trampoline bridge - x64
+ source/TrampolineBridge/ClosureTrampolineBridge/x64/helper_x64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/x64/closure_bridge_x64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc
+
+ source/InterceptRouting/Routing/InstructionInstrument/InstructionInstrument.cc
+ source/InterceptRouting/Routing/InstructionInstrument/RoutingImpl.cc
+ source/InterceptRouting/Routing/InstructionInstrument/instrument_routing_handler.cc
+
+ source/InterceptRouting/Routing/FunctionInlineHook/FunctionInlineHook.cc
+ source/InterceptRouting/Routing/FunctionInlineHook/RoutingImpl.cc
+
+ # plugin register
+ source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc
+
+ # main
+ source/dobby.cpp
+ source/Interceptor.cpp
+ source/InterceptEntry.cpp
+ )
+
+
+if (SYSTEM.Darwin AND NOT DOBBY_BUILD_KERNEL_MODE)
+ set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc
+
+ source/Backend/UserMode/UnifiedInterface/platform-posix.cc
+
+ source/Backend/UserMode/ExecMemory/code-patch-tool-darwin.cc
+ source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c
+ )
+
+elseif (SYSTEM.Linux OR SYSTEM.Android)
+ set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc
+
+ source/Backend/UserMode/UnifiedInterface/platform-posix.cc
+
+ source/Backend/UserMode/ExecMemory/code-patch-tool-posix.cc
+ source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c
+ )
+elseif (SYSTEM.Windows)
+ set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc
+
+ source/Backend/UserMode/UnifiedInterface/platform-windows.cc
+
+ source/Backend/UserMode/ExecMemory/code-patch-tool-windows.cc
+ source/Backend/UserMode/ExecMemory/clear-cache-tool-all.c
+ )
+endif ()
+
+if (PROCESSOR.X86_64 OR PROCESSOR.X86)
+ set(NearBranch ON)
+endif ()
+
+# ---
+
+if (0 AND SYSTEM.iOS AND (NOT DOBBY_BUILD_KERNEL_MODE))
+ include_directories(
+ source/Backend/UserMode/ExecMemory/substrated
+ )
+ set(compile_definitions "${compile_definitions} -DCODE_PATCH_WITH_SUBSTRATED")
+ set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ source/Backend/UserMode/ExecMemory/substrated/mach_interface_support
+ )
+endif ()
+
+# ----- instrument -----
+
+if (FunctionWrapper)
+ set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ # user mode - multi thread support
+ # source/UserMode/MultiThreadSupport/ThreadSupport.cpp
+ # source/UserMode/Thread/PlatformThread.cc
+ # source/UserMode/Thread/platform-thread-${platform1}.cc
+ )
+ message(FATAL_ERROR "[!] FunctionWrapper plugin is not supported")
+endif ()
+
+# ---
+
+if (NearBranch)
+ set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/near_trampoline_arm64.cc
+ source/InterceptRouting/RoutingPlugin/NearBranchTrampoline/NearBranchTrampoline.cc
+ source/MemoryAllocator/NearMemoryAllocator.cc)
+endif ()
+
+# ---
+
+# add logging library
+add_subdirectory(external/logging)
+get_target_property(logging.SOURCE_FILE_LIST logging SOURCES)
+
+# add osbase library
+add_subdirectory(external/osbase)
+
+# ---
+
+if (Plugin.SymbolResolver)
+ include_directories(builtin-plugin/SymbolResolver)
+ add_subdirectory(builtin-plugin/SymbolResolver)
+ get_target_property(symbol_resolver.SOURCE_FILE_LIST dobby_symbol_resolver SOURCES)
+ set(dobby.plugin.SOURCE_FILE_LIST ${dobby.plugin.SOURCE_FILE_LIST}
+ ${symbol_resolver.SOURCE_FILE_LIST}
+ )
+endif ()
+
+# ---
+
+set(dobby.HEADER_FILE_LIST
+ include/dobby.h
+ )
+
+# ---
+
+# add build version
+string(TIMESTAMP TODAY "%Y%m%d")
+set(VERSION_REVISION "-${TODAY}")
+if (EXISTS "${CMAKE_SOURCE_DIR}/.git")
+ execute_process(
+ COMMAND git rev-parse --short --verify HEAD
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ OUTPUT_VARIABLE VERSION_COMMIT_HASH
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if (VERSION_COMMIT_HASH)
+ set(VERSION_REVISION "${VERSION_REVISION}-${VERSION_COMMIT_HASH}")
+ endif ()
+endif ()
+set(DOBBY_BUILD_VERSION "Dobby${VERSION_REVISION}")
+set(compile_definitions "${compile_definitions} -D__DOBBY_BUILD_VERSION__=\"${DOBBY_BUILD_VERSION}\"")
+message(STATUS "[Dobby] ${DOBBY_BUILD_VERSION}")
+
+# ---
+
+set(SOURCE_FILE_LIST
+ ${dobby.HEADER_FILE_LIST}
+ ${dobby.SOURCE_FILE_LIST}
+ ${logging.SOURCE_FILE_LIST}
+ ${dobby.plugin.SOURCE_FILE_LIST}
+ )
+
+get_absolute_path_list(SOURCE_FILE_LIST SOURCE_FILE_LIST_)
+set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST_})
+
+add_library(dobby SHARED
+ ${SOURCE_FILE_LIST}
+ )
+
+target_include_directories(dobby PUBLIC
+ include
+ )
+
+# ---
+
+add_library(dobby_static STATIC
+ ${SOURCE_FILE_LIST}
+ )
+
+target_include_directories(dobby_static PUBLIC
+ include
+ )
+
+set_target_properties(dobby_static
+ PROPERTIES OUTPUT_NAME "dobby"
+ )
+
+# ---
+
+set_target_properties(dobby
+ PROPERTIES
+ LINK_FLAGS "${linker_flags}"
+ COMPILE_FLAGS "${compiler_flags}"
+ )
+
+set_target_properties(dobby_static
+ PROPERTIES
+ COMPILE_FLAGS "${compiler_flags}"
+ )
+
+target_compile_definitions(dobby PRIVATE
+ "COMPILE_DEFINITIONS ${compile_definitions}"
+ )
+target_compile_definitions(dobby_static PRIVATE
+ "COMPILE_DEFINITIONS ${compile_definitions}"
+ )
+
+# ---
+
+if (Private.Obfuscation)
+ set(linker_flags "${linker_flags} -Wl,-mllvm -Wl,-obfuscator-conf=all")
+endif ()
+
+# ---
+
+if (SYSTEM.Android)
+ target_link_libraries(dobby log)
+ if (PROCESSOR.ARM)
+ set_target_properties(dobby
+ PROPERTIES
+ ANDROID_ARM_MODE arm
+ )
+ set_target_properties(dobby_static
+ PROPERTIES
+ ANDROID_ARM_MODE arm
+ )
+ endif ()
+endif ()
+
+if (SYSTEM.Linux)
+ target_link_libraries(dobby dl)
+endif ()
+
+# ---
+
+if (DOBBY_BUILD_EXAMPLE AND (NOT DOBBY_BUILD_KERNEL_MODE))
+ add_subdirectory(examples)
+endif ()
+
+if (DOBBY_BUILD_TEST AND (NOT DOBBY_BUILD_KERNEL_MODE))
+ add_subdirectory(tests)
+endif ()
+
+# ---
+
+if (SYSTEM.Darwin AND (NOT DOBBY_BUILD_KERNEL_MODE))
+ include(cmake/platform/platform-darwin.cmake)
+endif ()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/LICENSE b/app/src/main/cpp/Dobby/LICENSE
new file mode 100644
index 0000000..f49a4e1
--- /dev/null
+++ b/app/src/main/cpp/Dobby/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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/app/src/main/cpp/Dobby/README.md b/app/src/main/cpp/Dobby/README.md
new file mode 100644
index 0000000..c0c0195
--- /dev/null
+++ b/app/src/main/cpp/Dobby/README.md
@@ -0,0 +1,26 @@
+## Dobby
+
+[![Contact me Telegram](https://img.shields.io/badge/Contact%20me-Telegram-blue.svg)](https://t.me/IOFramebuffer) [![Join group Telegram](https://img.shields.io/badge/Join%20group-Telegram-brightgreen.svg)](https://t.me/dobby_group)
+
+Dobby a lightweight, multi-platform, multi-architecture exploit hook framework.
+
+- Minimal and modular library
+- Multi-platform support(Windows/macOS/iOS/Android/Linux)
+- Multiple architecture support(X86, X86-64, ARM, ARM64)
+
+## Compile
+
+[docs/compile.md](docs/compile.md)
+
+## Download
+
+[download latest library](https://github.com/jmpews/Dobby/releases/tag/latest)
+
+## Credits
+
+1. [frida-gum](https://github.com/frida/frida-gum)
+2. [minhook](https://github.com/TsudaKageyu/minhook)
+3. [substrate](https://github.com/jevinskie/substrate).
+4. [v8](https://github.com/v8/v8)
+5. [dart](https://github.com/dart-lang/sdk)
+6. [vixl](https://git.linaro.org/arm/vixl.git)
diff --git a/app/src/main/cpp/Dobby/README_zh-cn.md b/app/src/main/cpp/Dobby/README_zh-cn.md
new file mode 100644
index 0000000..2f528b4
--- /dev/null
+++ b/app/src/main/cpp/Dobby/README_zh-cn.md
@@ -0,0 +1,3 @@
+## Dobby
+
+**å¾…æ›´æ–°**
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/MGCopyAnswerMonitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/MGCopyAnswerMonitor.cc
new file mode 100644
index 0000000..ddf2ee2
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/MGCopyAnswerMonitor.cc
@@ -0,0 +1,46 @@
+#include "./dobby_monitor.h"
+
+#include
+#include
+
+#define LOG_TAG "MGCopyAnswer"
+
+static uintptr_t getCallFirstArg(DobbyRegisterContext *ctx) {
+ uintptr_t result;
+#if defined(_M_X64) || defined(__x86_64__)
+#if defined(_WIN32)
+ result = ctx->general.regs.rcx;
+#else
+ result = ctx->general.regs.rdi;
+#endif
+#elif defined(__arm64__) || defined(__aarch64__)
+ result = ctx->general.regs.x0;
+#elif defined(__arm__)
+ result = ctx->general.regs.r0;
+#else
+#error "Not Support Architecture."
+#endif
+ return result;
+}
+
+void common_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) {
+ CFStringRef key_ = 0;
+ key_ = (CFStringRef)getCallFirstArg(ctx);
+
+ char str_key[256] = {0};
+ CFStringGetCString(key_, str_key, 256, kCFStringEncodingUTF8);
+ LOG("[#] MGCopyAnswer:: %s\n", str_key);
+}
+
+#if 0
+__attribute__((constructor)) static void ctor() {
+ void *lib = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_NOW);
+ void *MGCopyAnswer_addr = DobbySymbolResolver("libMobileGestalt.dylib", "MGCopyAnswer");
+
+ sleep(1);
+
+ dobby_enable_near_branch_trampoline();
+ DobbyInstrument((void *)MGCopyAnswer_addr, common_handler);
+ dobby_disable_near_branch_trampoline();
+}
+#endif
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/dynamic_loader_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/dynamic_loader_monitor.cc
new file mode 100644
index 0000000..3a9764d
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/dynamic_loader_monitor.cc
@@ -0,0 +1,94 @@
+#include /* getenv */
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include "dobby.h"
+
+#include "dobby/common.h"
+
+#define LOG_TAG "DynamicLoaderMonitor"
+
+std::unordered_map traced_dlopen_handle_list;
+
+static void *(*orig_dlopen)(const char *__file, int __mode);
+static void *fake_dlopen(const char *__file, int __mode) {
+ void *result = orig_dlopen(__file, __mode);
+ if (result != NULL && __file) {
+ char *traced_filename = (char *)malloc(MAXPATHLEN);
+ // FIXME: strncpy
+ strcpy(traced_filename, __file);
+ INFO_LOG("[-] dlopen handle: %s", __file);
+ traced_dlopen_handle_list.insert(std::make_pair(result, (const char *)traced_filename));
+ }
+ return result;
+}
+
+static void *(*orig_loader_dlopen)(const char *filename, int flags, const void *caller_addr);
+static void *fake_loader_dlopen(const char *filename, int flags, const void *caller_addr) {
+ void *result = orig_loader_dlopen(filename, flags, caller_addr);
+ if (result != NULL) {
+ char *traced_filename = (char *)malloc(MAXPATHLEN);
+ // FIXME: strncpy
+ strcpy(traced_filename, filename);
+ INFO_LOG("[-] dlopen handle: %s", filename);
+ traced_dlopen_handle_list.insert(std::make_pair(result, (const char *)traced_filename));
+ }
+ return result;
+}
+
+static const char *get_traced_filename(void *handle, bool removed) {
+ std::unordered_map::iterator it;
+ it = traced_dlopen_handle_list.find(handle);
+ if (it != traced_dlopen_handle_list.end()) {
+ if (removed)
+ traced_dlopen_handle_list.erase(it);
+ return it->second;
+ }
+ return NULL;
+}
+
+static void *(*orig_dlsym)(void *__handle, const char *__symbol);
+static void *fake_dlsym(void *__handle, const char *__symbol) {
+ const char *traced_filename = get_traced_filename(__handle, false);
+ if (traced_filename) {
+ INFO_LOG("[-] dlsym: %s, symbol: %s", traced_filename, __symbol);
+ }
+ return orig_dlsym(__handle, __symbol);
+}
+
+static int (*orig_dlclose)(void *__handle);
+static int fake_dlclose(void *__handle) {
+ const char *traced_filename = get_traced_filename(__handle, true);
+ if (traced_filename) {
+ INFO_LOG("[-] dlclose: %s", traced_filename);
+ free((void *)traced_filename);
+ }
+ return orig_dlclose(__handle);
+}
+
+#if 0
+__attribute__((constructor)) static void ctor() {
+#if defined(__ANDROID__)
+#if 0
+ void *dl = dlopen("libdl.so", RTLD_LAZY);
+ void *__loader_dlopen = dlsym(dl, "__loader_dlopen");
+#endif
+ DobbyHook((void *)DobbySymbolResolver(NULL, "__loader_dlopen"), (void *)fake_loader_dlopen,
+ (void **)&orig_loader_dlopen);
+#else
+ DobbyHook((void *)DobbySymbolResolver(NULL, "dlopen"), (void *)fake_dlopen, (void **)&orig_dlopen);
+#endif
+
+ DobbyHook((void *)dlsym, (void *)fake_dlsym, (void **)&orig_dlsym);
+ DobbyHook((void *)dlclose, (void *)fake_dlclose, (void **)&orig_dlclose);
+}
+#endif
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/file_operation_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/file_operation_monitor.cc
new file mode 100644
index 0000000..d4f09ca
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/file_operation_monitor.cc
@@ -0,0 +1,97 @@
+#include /* getenv */
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include "./dobby_monitor.h"
+
+std::unordered_map *TracedFopenFileList;
+
+FILE *(*orig_fopen)(const char *filename, const char *mode);
+FILE *fake_fopen(const char *filename, const char *mode) {
+ FILE *result = NULL;
+ result = orig_fopen(filename, mode);
+ if (result != NULL) {
+ char *traced_filename = (char *)malloc(MAXPATHLEN);
+ // FIXME: strncpy
+ strcpy(traced_filename, filename);
+ std::cout << "[-] trace file: " << filename << std::endl;
+ TracedFopenFileList->insert(std::make_pair(result, traced_filename));
+ }
+ return result;
+}
+
+static const char *GetFileDescriptorTraced(FILE *stream, bool removed) {
+ std::unordered_map::iterator it;
+ it = TracedFopenFileList->find(stream);
+ if (it != TracedFopenFileList->end()) {
+ if (removed)
+ TracedFopenFileList->erase(it);
+ return it->second;
+ }
+ return NULL;
+}
+
+size_t (*orig_fread)(void *ptr, size_t size, size_t count, FILE *stream);
+size_t fake_fread(void *ptr, size_t size, size_t count, FILE *stream) {
+ const char *file_name = GetFileDescriptorTraced(stream, false);
+ if (file_name) {
+ LOG("[-] fread: %s, buffer: %p\n", file_name, ptr);
+ }
+ return orig_fread(ptr, size, count, stream);
+}
+
+size_t (*orig_fwrite)(const void *ptr, size_t size, size_t count, FILE *stream);
+size_t fake_fwrite(void *ptr, size_t size, size_t count, FILE *stream) {
+ const char *file_name = GetFileDescriptorTraced(stream, false);
+ if (file_name) {
+ LOG("[-] fwrite %s\n from %p\n", file_name, ptr);
+ }
+ return orig_fwrite(ptr, size, count, stream);
+}
+
+__attribute__((constructor)) void __main() {
+
+ TracedFopenFileList = new std::unordered_map();
+
+#if defined(__APPLE__)
+#include
+#if (TARGET_OS_IPHONE || TARGET_OS_MAC)
+ std::ifstream file;
+ file.open("/System/Library/CoreServices/SystemVersion.plist");
+ std::cout << file.rdbuf();
+#endif
+#endif
+
+ // DobbyHook((void *)fopen, (void *)fake_fopen, (void **)&orig_fopen);
+ // DobbyHook((void *)fwrite, (void *)fake_fwrite, (void **)&orig_fwrite);
+ // DobbyHook((void *)fread, (void *)fake_fread, (void **)&orig_fread);
+
+ char *home = getenv("HOME");
+ char *subdir = (char *)"/Library/Caches/";
+
+ std::string filePath = std::string(home) + std::string(subdir) + "temp.log";
+
+ char buffer[64];
+ memset(buffer, 'B', 64);
+
+ FILE *fd = fopen(filePath.c_str(), "w+");
+ if (!fd)
+ std::cout << "[!] open " << filePath << "failed!\n";
+
+ fwrite(buffer, 64, 1, fd);
+ fflush(fd);
+ fseek(fd, 0, SEEK_SET);
+ memset(buffer, 0, 64);
+
+ fread(buffer, 64, 1, fd);
+
+ return;
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/memory_operation_instrument.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/memory_operation_instrument.cc
new file mode 100644
index 0000000..0298275
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/memory_operation_instrument.cc
@@ -0,0 +1,58 @@
+#include "./dobby_monitor.h"
+
+#include
+#include
+#include
+
+static uintptr_t getCallFirstArg(DobbyRegisterContext *ctx) {
+ uintptr_t result;
+#if defined(_M_X64) || defined(__x86_64__)
+#if defined(_WIN32)
+ result = ctx->general.regs.rcx;
+#else
+ result = ctx->general.regs.rdi;
+#endif
+#elif defined(__arm64__) || defined(__aarch64__)
+ result = ctx->general.regs.x0;
+#elif defined(__arm__)
+ result = ctx->general.regs.r0;
+#else
+#error "Not Support Architecture."
+#endif
+ return result;
+}
+
+void format_integer_manually(char *buf, uint64_t integer) {
+ int tmp = 0;
+ for (tmp = (int)integer; tmp > 0; tmp = (tmp >> 4)) {
+ buf += (tmp % 16);
+ buf--;
+ }
+}
+
+// [ATTENTION]:
+// printf will call 'malloc' internally, and will crash in a loop.
+// so, use 'puts' is a better choice.
+void malloc_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) {
+ size_t size_ = 0;
+ size_ = getCallFirstArg(ctx);
+ char *buffer_ = (char *)"[-] function malloc first arg: 0x00000000.\n";
+ format_integer_manually(strchr(buffer_, '.') - 1, size_);
+ puts(buffer_);
+}
+
+void free_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) {
+ uintptr_t mem_ptr;
+
+ mem_ptr = getCallFirstArg(ctx);
+
+ char *buffer = (char *)"[-] function free first arg: 0x00000000.\n";
+ format_integer_manually(strchr(buffer, '.') - 1, mem_ptr);
+ puts(buffer);
+}
+
+__attribute__((constructor)) static void ctor() {
+ // DobbyInstrument((void *)mmap, malloc_handler);
+ // DobbyInstrument((void *)free, free_handler);
+ return;
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_file_descriptor_operation_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_file_descriptor_operation_monitor.cc
new file mode 100644
index 0000000..4c0db6c
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_file_descriptor_operation_monitor.cc
@@ -0,0 +1,120 @@
+#include /* getenv */
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include "dobby.h"
+#include "dobby/common.h"
+
+#define LOG_TAG "PosixFileOperationMonitor"
+
+std::unordered_map *posix_file_descriptors;
+
+int (*orig_open)(const char *pathname, int flags, ...);
+int fake_open(const char *pathname, int flags, ...) {
+ mode_t mode = 0;
+ if (flags & O_CREAT) {
+ va_list args;
+ va_start(args, flags);
+ mode = (mode_t)va_arg(args, int);
+ va_end(args);
+ }
+
+ int result = orig_open(pathname, flags, mode);
+ if (result != -1) {
+ char *traced_filename = (char *)malloc(MAXPATHLEN);
+ // FIXME: strncpy
+ strcpy(traced_filename, pathname);
+ INFO_LOG("[-] trace open handle: %s", pathname);
+
+ if (posix_file_descriptors == NULL) {
+ posix_file_descriptors = new std::unordered_map();
+ }
+ posix_file_descriptors->insert(std::make_pair(result, (const char *)traced_filename));
+ }
+ return result;
+}
+
+int (*orig___open)(const char *pathname, int flags, int mode);
+int fake___open(const char *pathname, int flags, int mode) {
+ char *traced_filename = NULL;
+ if (pathname) {
+ traced_filename = (char *)malloc(MAXPATHLEN);
+ // FIXME: strncpy
+ strcpy(traced_filename, pathname);
+ INFO_LOG("[-] trace open handle: ", pathname);
+ }
+ int result = orig___open(pathname, flags, mode);
+ if (result != -1) {
+ if (posix_file_descriptors == NULL) {
+ posix_file_descriptors = new std::unordered_map();
+ }
+ posix_file_descriptors->insert(std::make_pair(result, (const char *)traced_filename));
+ }
+ return result;
+}
+
+static const char *get_traced_filename(int fd, bool removed) {
+ if (posix_file_descriptors == NULL)
+ return NULL;
+ std::unordered_map::iterator it;
+ it = posix_file_descriptors->find(fd);
+ if (it != posix_file_descriptors->end()) {
+ if (removed)
+ posix_file_descriptors->erase(it);
+ return it->second;
+ }
+ return NULL;
+}
+
+ssize_t (*orig_read)(int fd, void *buf, size_t count);
+ssize_t fake_read(int fd, void *buf, size_t count) {
+ const char *traced_filename = get_traced_filename(fd, false);
+ if (traced_filename) {
+ INFO_LOG("[-] read: %s, buffer: %p, size: %zu", traced_filename, buf, count);
+ }
+ return orig_read(fd, buf, count);
+}
+
+ssize_t (*orig_write)(int fd, const void *buf, size_t count);
+ssize_t fake_write(int fd, const void *buf, size_t count) {
+ const char *traced_filename = get_traced_filename(fd, false);
+ if (traced_filename) {
+ INFO_LOG("[-] write: %s, buffer: %p, size: %zu", traced_filename, buf, count);
+ }
+ return orig_write(fd, buf, count);
+}
+int (*orig_close)(int fd);
+int fake_close(int fd) {
+ const char *traced_filename = get_traced_filename(fd, true);
+ if (traced_filename) {
+ INFO_LOG("[-] close: %s", traced_filename);
+ free((void *)traced_filename);
+ }
+ return orig_close(fd);
+}
+
+#if 0
+__attribute__((constructor)) static void ctor() {
+ DobbyHook((void *)DobbySymbolResolver(NULL, "open"), (void *)fake_open, (void **)&orig_open);
+
+ DobbyHook((void *)DobbySymbolResolver(NULL, "write"), (void *)fake_write, (void **)&orig_write);
+
+ DobbyHook((void *)DobbySymbolResolver(NULL, "read"), (void *)fake_read, (void **)&orig_read);
+
+ DobbyHook((void *)DobbySymbolResolver(NULL, "close"), (void *)fake_close, (void **)&orig_close);
+}
+#endif
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_socket_network_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_socket_network_monitor.cc
new file mode 100644
index 0000000..a6e6e6c
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ApplicationEventMonitor/posix_socket_network_monitor.cc
@@ -0,0 +1,57 @@
+#include /* getenv */
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+#include
+#include
+
+std::unordered_map posix_socket_file_descriptors;
+
+int (*orig_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+int fake_bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
+}
+
+static const char *get_traced_socket(int fd, bool removed) {
+ std::unordered_map::iterator it;
+ it = posix_socket_file_descriptors.find(fd);
+ if (it != posix_socket_file_descriptors.end()) {
+ if (removed)
+ posix_socket_file_descriptors.erase(it);
+ return it->second;
+ }
+ return NULL;
+}
+
+int (*orig_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+int fake_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
+ const char *traced_socket = get_traced_socket(sockfd, false);
+ if (traced_socket) {
+ INFO_LOG("[-] connect: %s\n", traced_socket);
+ }
+ return orig_connect(sockfd, addr, addrlen);
+}
+
+ssize_t (*orig_send)(int sockfd, const void *buf, size_t len, int flags);
+ssize_t fake_send(int sockfd, const void *buf, size_t len, int flags) {
+ const char *traced_socket = get_traced_socket(sockfd, false);
+ if (traced_socket) {
+ INFO_LOG("[-] send: %s, buf: %p, len: %zu\n", traced_socket, buf, len);
+ }
+ return orig_send(sockfd, buf, len, flags);
+}
+
+ssize_t (*orig_recv)(int sockfd, void *buf, size_t len, int flags);
+ssize_t fake_recv(int sockfd, void *buf, size_t len, int flags) {
+ const char *traced_socket = get_traced_socket(sockfd, false);
+ if (traced_socket) {
+ INFO_LOG("[-] recv: %s, buf: %p, len: %zu\n", traced_socket, buf, len);
+ }
+ return orig_recv(sockfd, buf, len, flags);
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_demo.cc b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_demo.cc
new file mode 100644
index 0000000..f68264c
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_demo.cc
@@ -0,0 +1,36 @@
+#include "dobby.h"
+
+#include "bionic_linker_util.h"
+
+#include "logging/logging.h"
+
+#include
+
+#define LOG_TAG "BionicLinkerUtil"
+
+__attribute__((constructor)) static void ctor() {
+ const char *lib = NULL;
+
+#if defined(__LP64__)
+ lib = "/system/lib64/libandroid_runtime.so";
+#else
+ lib = "/system/lib/libandroid_runtime.so";
+#endif
+
+ void *vm = NULL;
+
+ vm = DobbySymbolResolver(lib, "_ZN7android14AndroidRuntime7mJavaVME");
+ INFO_LOG("DobbySymbolResolver::vm %p", vm);
+
+#if 0
+ linker_disable_namespace_restriction();
+ void *handle = NULL;
+ handle = dlopen(lib, RTLD_LAZY);
+ vm = dlsym(handle, "_ZN7android14AndroidRuntime7mJavaVME");
+#else
+ void *handle = NULL;
+ handle = linker_dlopen(lib, RTLD_LAZY);
+ vm = dlsym(handle, "_ZN7android14AndroidRuntime7mJavaVME");
+#endif
+ INFO_LOG("vm %p", vm);
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.cc b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.cc
new file mode 100644
index 0000000..8b995e8
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.cc
@@ -0,0 +1,197 @@
+#include "bionic_linker_util.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include "dobby.h"
+#include "dobby_symbol_resolver.h"
+
+#include "dobby/common.h"
+
+#undef LOG_TAG
+#define LOG_TAG "BionicLinkerUtil"
+
+#undef Q
+#define Q 29
+// impl at "dobby_symbol_resolver.cc"
+extern void *resolve_elf_internal_symbol(const char *library_name, const char *symbol_name);
+
+#include
+static int get_android_system_version() {
+ char os_version_str[PROP_VALUE_MAX + 1];
+ __system_property_get("ro.build.version.sdk", os_version_str);
+ int os_version_int = atoi(os_version_str);
+ return os_version_int;
+}
+
+static const char *get_android_linker_path() {
+#if __LP64__
+ if (get_android_system_version() >= Q) {
+ return (const char *)"/apex/com.android.runtime/bin/linker64";
+ } else {
+ return (const char *)"/system/bin/linker64";
+ }
+#else
+ if (get_android_system_version() >= Q) {
+ return (const char *)"/apex/com.android.runtime/bin/linker";
+ } else {
+ return (const char *)"/system/bin/linker";
+ }
+#endif
+}
+
+PUBLIC void *linker_dlopen(const char *filename, int flag) {
+ typedef void *(*__loader_dlopen_t)(const char *filename, int flags, const void *caller_addr);
+ static __loader_dlopen_t __loader_dlopen = NULL;
+ if (!__loader_dlopen)
+ __loader_dlopen = (__loader_dlopen_t)DobbySymbolResolver(NULL, "__loader_dlopen");
+
+ // fake caller address
+ void *open_ptr = dlsym(RTLD_DEFAULT, "open");
+ return __loader_dlopen(filename, flag, (const void *)open_ptr);
+}
+
+std::vector linker_solist;
+std::vector linker_get_solist() {
+ if (!linker_solist.empty()) {
+ linker_solist.clear();
+ }
+
+ static soinfo_t (*solist_get_head)() = NULL;
+ if (!solist_get_head)
+ solist_get_head =
+ (soinfo_t(*)())resolve_elf_internal_symbol(get_android_linker_path(), "__dl__Z15solist_get_headv");
+
+ static soinfo_t (*solist_get_somain)() = NULL;
+ if (!solist_get_somain)
+ solist_get_somain =
+ (soinfo_t(*)())resolve_elf_internal_symbol(get_android_linker_path(), "__dl__Z17solist_get_somainv");
+
+ static addr_t *solist_head = NULL;
+ if (!solist_head)
+ solist_head = (addr_t *)solist_get_head();
+
+ static addr_t somain = 0;
+ if (!somain)
+ somain = (addr_t)solist_get_somain();
+
+ // Generate the name for an offset.
+#define PARAM_OFFSET(type_, member_) __##type_##__##member_##__offset_
+#define STRUCT_OFFSET PARAM_OFFSET
+ int STRUCT_OFFSET(solist, next) = 0;
+ for (size_t i = 0; i < 1024 / sizeof(void *); i++) {
+ if (*(addr_t *)((addr_t)solist_head + i * sizeof(void *)) == somain) {
+ STRUCT_OFFSET(solist, next) = i * sizeof(void *);
+ break;
+ }
+ }
+
+ linker_solist.push_back(solist_head);
+
+ addr_t sonext = 0;
+ sonext = *(addr_t *)((addr_t)solist_head + STRUCT_OFFSET(solist, next));
+ while (sonext) {
+ linker_solist.push_back((void *)sonext);
+ sonext = *(addr_t *)((addr_t)sonext + STRUCT_OFFSET(solist, next));
+ }
+
+ return linker_solist;
+}
+
+char *linker_soinfo_get_realpath(soinfo_t soinfo) {
+ static char *(*_get_realpath)(soinfo_t) = NULL;
+ if (!_get_realpath)
+ _get_realpath =
+ (char *(*)(soinfo_t))resolve_elf_internal_symbol(get_android_linker_path(), "__dl__ZNK6soinfo12get_realpathEv");
+ return _get_realpath(soinfo);
+}
+
+uintptr_t linker_soinfo_to_handle(soinfo_t soinfo) {
+ static uintptr_t (*_linker_soinfo_to_handle)(soinfo_t) = NULL;
+ if (!_linker_soinfo_to_handle)
+ _linker_soinfo_to_handle =
+ (uintptr_t(*)(soinfo_t))resolve_elf_internal_symbol(get_android_linker_path(), "__dl__ZN6soinfo9to_handleEv");
+ return _linker_soinfo_to_handle(soinfo);
+}
+
+typedef void *android_namespace_t;
+android_namespace_t linker_soinfo_get_primary_namespace(soinfo_t soinfo) {
+ static android_namespace_t (*_get_primary_namespace)(soinfo_t) = NULL;
+ if (!_get_primary_namespace)
+ _get_primary_namespace = (android_namespace_t(*)(soinfo_t))resolve_elf_internal_symbol(
+ get_android_linker_path(), "__dl__ZN6soinfo21get_primary_namespaceEv");
+ return _get_primary_namespace(soinfo);
+}
+
+void linker_iterate_soinfo(int (*cb)(soinfo_t soinfo)) {
+ auto solist = linker_get_solist();
+ for (auto it = solist.begin(); it != solist.end(); it++) {
+ int ret = cb(*it);
+ if (ret != 0)
+ break;
+ }
+}
+
+static int iterate_soinfo_cb(soinfo_t soinfo) {
+ android_namespace_t ns = NULL;
+ ns = linker_soinfo_get_primary_namespace(soinfo);
+ INFO_LOG("lib: %s", linker_soinfo_get_realpath(soinfo));
+
+ // set is_isolated_ as false
+ // no need for this actually
+ int STRUCT_OFFSET(android_namespace_t, is_isolated_) = 0x8;
+ *(uint8_t *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, is_isolated_)) = false;
+
+ std::vector ld_library_paths = {"/system/lib64", "/sytem/lib"};
+ if (get_android_system_version() >= Q) {
+ ld_library_paths.push_back("/apex/com.android.runtime/lib64");
+ ld_library_paths.push_back("/apex/com.android.runtime/lib");
+ }
+ int STRUCT_OFFSET(android_namespace_t, ld_library_paths_) = 0x10;
+ if (*(void **)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_))) {
+ std::vector orig_ld_library_paths =
+ *(std::vector *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_));
+ orig_ld_library_paths.insert(orig_ld_library_paths.end(), ld_library_paths.begin(), ld_library_paths.end());
+
+ // remove duplicates
+ {
+ std::set paths(orig_ld_library_paths.begin(), orig_ld_library_paths.end());
+ orig_ld_library_paths.assign(paths.begin(), paths.end());
+ }
+ } else {
+ *(std::vector *)((addr_t)ns + STRUCT_OFFSET(android_namespace_t, ld_library_paths_)) =
+ std::move(ld_library_paths);
+ }
+ return 0;
+}
+
+bool (*orig_linker_namespace_is_is_accessible)(android_namespace_t ns, const std::string &file);
+bool linker_namespace_is_is_accessible(android_namespace_t ns, const std::string &file) {
+ INFO_LOG("check %s", file.c_str());
+ return true;
+ return orig_linker_namespace_is_is_accessible(ns, file);
+}
+
+void linker_disable_namespace_restriction() {
+ linker_iterate_soinfo(iterate_soinfo_cb);
+
+ // no need for this actually
+ void *linker_namespace_is_is_accessible_ptr = resolve_elf_internal_symbol(
+ get_android_linker_path(), "__dl__ZN19android_namespace_t13is_accessibleERKNSt3__112basic_"
+ "stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE");
+ DobbyHook(linker_namespace_is_is_accessible_ptr, (void *)linker_namespace_is_is_accessible,
+ (void **)&orig_linker_namespace_is_is_accessible);
+
+ INFO_LOG("disable namespace restriction done");
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.h b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.h
new file mode 100644
index 0000000..55c2911
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/BionicLinkerUtil/bionic_linker_util.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *soinfo_t;
+
+soinfo_t linker_dlopen(const char *filename, int flag);
+
+char *linker_soinfo_get_realpath(soinfo_t soinfo);
+
+uintptr_t linker_soinfo_to_handle(soinfo_t soinfo);
+
+void linker_iterate_soinfo(int (*cb)(soinfo_t soinfo));
+
+void linker_disable_namespace_restriction();
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/CMakeLists.txt
new file mode 100644
index 0000000..3730cb9
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/CMakeLists.txt
@@ -0,0 +1,15 @@
+if (Plugin.ImportTableReplace AND SYSTEM.Darwin)
+ message(STATUS "[Dobby] Enable got hook")
+ include_directories(builtin-plugin/ImportTableReplace)
+ add_subdirectory(builtin-plugin/ImportTableReplace)
+endif ()
+
+if (Plugin.Android.BionicLinkerUtil)
+ if (NOT SYSTEM.Android)
+ message(FATAL_ERROR "[!] Plugin.Android.BionicLinkerUtil only works on Android.")
+ endif ()
+ message(STATUS "[Dobby] Enable Plugin.Android.BionicLinkerUtil")
+ set(dobby.plugin.SOURCE_FILE_LIST ${dobby.plugin.SOURCE_FILE_LIST}
+ BionicLinkerUtil/bionic_linker_util.cc
+ )
+endif ()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/CMakeLists.txt
new file mode 100644
index 0000000..1a2b4b3
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_library(dobby_import_replace INTERFACE
+ dobby_import_replace.cc
+ )
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.cc b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.cc
new file mode 100644
index 0000000..eab1af9
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.cc
@@ -0,0 +1,192 @@
+#include "dobby_import_replace.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include "dobby/common.h"
+
+#include "logging/logging.h"
+
+#include "PlatformUtil/ProcessRuntimeUtility.h"
+
+#if defined(__LP64__)
+typedef struct mach_header_64 mach_header_t;
+typedef struct segment_command_64 segment_command_t;
+typedef struct section_64 section_t;
+typedef struct nlist_64 nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64
+#else
+typedef struct mach_header mach_header_t;
+typedef struct segment_command segment_command_t;
+typedef struct section section_t;
+typedef struct nlist nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT
+#endif
+
+static void *iterate_indirect_symtab(char *symbol_name, section_t *section, intptr_t slide, nlist_t *symtab,
+ char *strtab, uint32_t *indirect_symtab) {
+ const bool is_data_const = strcmp(section->segname, "__DATA_CONST") == 0;
+ uint32_t *indirect_symbol_indices = indirect_symtab + section->reserved1;
+ void **indirect_symbol_bindings = (void **)((uintptr_t)slide + section->addr);
+
+ vm_prot_t old_protection = VM_PROT_READ;
+ if (is_data_const) {
+ mprotect(indirect_symbol_bindings, section->size, PROT_READ | PROT_WRITE);
+ }
+
+ for (uint i = 0; i < section->size / sizeof(void *); i++) {
+ uint32_t symtab_index = indirect_symbol_indices[i];
+ if (symtab_index == INDIRECT_SYMBOL_ABS || symtab_index == INDIRECT_SYMBOL_LOCAL ||
+ symtab_index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS)) {
+ continue;
+ }
+ uint32_t strtab_offset = symtab[symtab_index].n_un.n_strx;
+ char *local_symbol_name = strtab + strtab_offset;
+ bool symbol_name_longer_than_1 = symbol_name[0] && symbol_name[1];
+ if (strcmp(local_symbol_name, symbol_name) == 0) {
+ return &indirect_symbol_bindings[i];
+ }
+ if (local_symbol_name[0] == '_') {
+ if (strcmp(symbol_name, &local_symbol_name[1]) == 0) {
+ return &indirect_symbol_bindings[i];
+ }
+ }
+ }
+
+ if (is_data_const && 0) {
+ int protection = 0;
+ if (old_protection & VM_PROT_READ) {
+ protection |= PROT_READ;
+ }
+ if (old_protection & VM_PROT_WRITE) {
+ protection |= PROT_WRITE;
+ }
+ if (old_protection & VM_PROT_EXECUTE) {
+ protection |= PROT_EXEC;
+ }
+ mprotect(indirect_symbol_bindings, section->size, protection);
+ }
+ return NULL;
+}
+
+static void *get_global_offset_table_stub(mach_header_t *header, char *symbol_name) {
+ segment_command_t *curr_seg_cmd;
+ segment_command_t *text_segment, *data_segment, *linkedit_segment;
+ struct symtab_command *symtab_cmd = NULL;
+ struct dysymtab_command *dysymtab_cmd = NULL;
+
+ uintptr_t cur = (uintptr_t)header + sizeof(mach_header_t);
+ for (uint i = 0; i < header->ncmds; i++, cur += curr_seg_cmd->cmdsize) {
+ curr_seg_cmd = (segment_command_t *)cur;
+ if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) {
+ if (strcmp(curr_seg_cmd->segname, "__LINKEDIT") == 0) {
+ linkedit_segment = curr_seg_cmd;
+ } else if (strcmp(curr_seg_cmd->segname, "__DATA") == 0) {
+ data_segment = curr_seg_cmd;
+ } else if (strcmp(curr_seg_cmd->segname, "__TEXT") == 0) {
+ text_segment = curr_seg_cmd;
+ }
+ } else if (curr_seg_cmd->cmd == LC_SYMTAB) {
+ symtab_cmd = (struct symtab_command *)curr_seg_cmd;
+ } else if (curr_seg_cmd->cmd == LC_DYSYMTAB) {
+ dysymtab_cmd = (struct dysymtab_command *)curr_seg_cmd;
+ }
+ }
+
+ if (!symtab_cmd || !linkedit_segment || !linkedit_segment) {
+ return NULL;
+ }
+
+ uintptr_t slide = (uintptr_t)header - (uintptr_t)text_segment->vmaddr;
+ uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff;
+ nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff);
+ char *strtab = (char *)(linkedit_base + symtab_cmd->stroff);
+ uint32_t symtab_count = symtab_cmd->nsyms;
+
+ uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff);
+
+ cur = (uintptr_t)header + sizeof(mach_header_t);
+ for (uint i = 0; i < header->ncmds; i++, cur += curr_seg_cmd->cmdsize) {
+ curr_seg_cmd = (segment_command_t *)cur;
+ if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) {
+ if (strcmp(curr_seg_cmd->segname, "__DATA") != 0 && strcmp(curr_seg_cmd->segname, "__DATA_CONST") != 0) {
+ continue;
+ }
+ for (uint j = 0; j < curr_seg_cmd->nsects; j++) {
+ section_t *sect = (section_t *)(cur + sizeof(segment_command_t)) + j;
+ if ((sect->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS) {
+ void *stub = iterate_indirect_symtab(symbol_name, sect, slide, symtab, strtab, indirect_symtab);
+ if (stub)
+ return stub;
+ }
+ if ((sect->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS) {
+ void *stub = iterate_indirect_symtab(symbol_name, sect, slide, symtab, strtab, indirect_symtab);
+ if (stub)
+ return stub;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+PUBLIC int DobbyImportTableReplace(char *image_name, char *symbol_name, void *fake_func, void **orig_func_ptr) {
+ std::vector ProcessModuleMap = ProcessRuntimeUtility::GetProcessModuleMap();
+
+ for (auto module : ProcessModuleMap) {
+ if (image_name != NULL && strstr(module.path, image_name) == NULL)
+ continue;
+
+ addr_t header = (addr_t)module.load_address;
+ size_t slide = 0;
+
+#if 0
+ if (header) {
+ if (((struct mach_header *)header)->magic == MH_MAGIC_64)
+ slide = macho_kit_get_slide64(header);
+ }
+#endif
+
+#if 0
+ INFO_LOG("resolve image: %s", module.path);
+#endif
+
+ uint32_t nlist_count = 0;
+ nlist_t *nlist_array = 0;
+ char *string_pool = 0;
+
+ void *stub = get_global_offset_table_stub((mach_header_t *)header, symbol_name);
+ if (stub) {
+ void *orig_func;
+ orig_func = *(void **)stub;
+#if __has_feature(ptrauth_calls)
+ orig_func = ptrauth_strip(orig_func, ptrauth_key_asia);
+ orig_func = ptrauth_sign_unauthenticated(orig_func, ptrauth_key_asia, 0);
+#endif
+ *orig_func_ptr = orig_func;
+
+#if __has_feature(ptrauth_calls)
+ fake_func = (void *)ptrauth_strip(fake_func, ptrauth_key_asia);
+ fake_func = ptrauth_sign_unauthenticated(fake_func, ptrauth_key_asia, stub);
+#endif
+ *(void **)stub = fake_func;
+ }
+
+ if (image_name)
+ return 0;
+ }
+ return -1;
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.h b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.h
new file mode 100644
index 0000000..c51b0f7
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ImportTableReplace/dobby_import_replace.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// int DobbyImportTableReplace(char *image_name, char *symbol_name, void *fake_func, void **orig_func);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/CMakeLists.txt
new file mode 100644
index 0000000..5430d9f
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_library(objc_runtime_replace
+ dobby_objc_runtime_replace.mm
+ )
+
+target_link_libraries(objc_runtime_replace
+ "-framework Foundation"
+ )
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_repalce.h b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_repalce.h
new file mode 100644
index 0000000..da959e7
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_repalce.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+IMP DobbyObjcReplace(Class _class, SEL _selector, IMP replacement);
+
+void DobbyObjcReplaceEx(const char *class_name, const char *selector_name, void *fake_impl, void **orig_impl);
+
+void *DobbyObjcResolveMethodImp(const char *class_name, const char *selector_name);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_replace.mm b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_replace.mm
new file mode 100644
index 0000000..d794880
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/ObjcRuntimeReplace/dobby_objc_runtime_replace.mm
@@ -0,0 +1,54 @@
+#include "dobby_objc_runtime_repalce.h"
+
+#include
+#include
+
+/* clang -rewrite-objc main.m */
+
+IMP DobbyObjcReplace(Class class_, SEL sel_, IMP fake_impl) {
+ Method method_ = class_getInstanceMethod(class_, sel_);
+ if (!method_)
+ method_ = class_getClassMethod(class_, sel_);
+
+ if (!method_) {
+ // DEBUG_LOG("Not found class: %s, selector: %s method\n", class_getName(class_), sel_getName(sel_));
+ return NULL;
+ }
+
+ return method_setImplementation(method_, (IMP)fake_impl);
+}
+
+void DobbyObjcReplaceEx(const char *class_name, const char *selector_name, void *fake_impl, void **out_orig_impl) {
+ Class class_ = objc_getClass(class_name);
+ SEL sel_ = sel_registerName(selector_name);
+
+ Method method_ = class_getInstanceMethod(class_, sel_);
+ if (!method_) {
+ method_ = class_getClassMethod(class_, sel_);
+ if (!method_) {
+ // ERROR_LOG("Not found class: %s, selector: %s method\n", class_name, selector_name);
+ return;
+ }
+ }
+
+ auto orig_impl = (void *)method_setImplementation(method_, (IMP)fake_impl);
+ if (out_orig_impl) {
+ *out_orig_impl = orig_impl;
+ }
+ return;
+}
+
+void *DobbyObjcResolveMethodImp(const char *class_name, const char *selector_name) {
+ Class class_ = objc_getClass(class_name);
+ SEL sel_ = sel_registerName(selector_name);
+
+ Method method_ = class_getInstanceMethod(class_, sel_);
+ if (!method_)
+ method_ = class_getClassMethod(class_, sel_);
+
+ if (!method_) {
+ // DEBUG_LOG("Not found class: %s, selector: %s method\n", class_name, selector_name);
+ return NULL;
+ }
+ return (void *)method_getImplementation(method_);
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/CMakeLists.txt
new file mode 100644
index 0000000..ddddfd7
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/CMakeLists.txt
@@ -0,0 +1,23 @@
+add_library(supervisor_call_monitor STATIC
+ mach_system_call_log_handler.cc
+ system_call_log_handler.cc
+ supervisor_call_monitor.cc
+ sensitive_api_monitor.cc
+ misc_utility.cc
+ )
+target_link_libraries(supervisor_call_monitor
+ misc_helper
+ dobby
+ )
+
+add_library(test_supervisor_call_monitor SHARED
+ test_supervisor_call_monitor.cc
+ )
+target_link_libraries(test_supervisor_call_monitor
+ supervisor_call_monitor
+)
+
+include_directories(
+ .
+)
+
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/README b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/README
new file mode 100644
index 0000000..3832eb5
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/README
@@ -0,0 +1 @@
+Monitor all supervisor call
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/mach_system_call_log_handler.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/mach_system_call_log_handler.cc
new file mode 100644
index 0000000..970a1be
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/mach_system_call_log_handler.cc
@@ -0,0 +1,193 @@
+#include "dobby/dobby_internal.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "misc-helper/async_logger.h"
+#include "PlatformUtil/ProcessRuntimeUtility.h"
+#include "SupervisorCallMonitor/misc_utility.h"
+#include "SupervisorCallMonitor/supervisor_call_monitor.h"
+
+#include "XnuInternal/syscall_sw.c"
+
+#include "XnuInternal/mach/clock_priv.h"
+#include "XnuInternal/mach/clock_reply.h"
+#include "XnuInternal/mach/clock.h"
+#include "XnuInternal/mach/exc.h"
+#include "XnuInternal/mach/host_priv.h"
+#include "XnuInternal/mach/host_security.h"
+#include "XnuInternal/mach/lock_set.h"
+#include "XnuInternal/mach/mach_host.h"
+#include "XnuInternal/mach/mach_port.h"
+#include "XnuInternal/mach/mach_vm.h"
+#include "XnuInternal/mach/mach_voucher.h"
+#include "XnuInternal/mach/memory_entry.h"
+#include "XnuInternal/mach/processor_set.h"
+#include "XnuInternal/mach/processor.h"
+#include "XnuInternal/mach/task.h"
+#include "XnuInternal/mach/thread_act.h"
+#include "XnuInternal/mach/vm_map.h"
+
+typedef struct {
+ char *mach_msg_name;
+ int mach_msg_id;
+} mach_msg_entry_t;
+
+// clang-format off
+mach_msg_entry_t mach_msg_array[] = {
+ subsystem_to_name_map_clock_priv,
+ subsystem_to_name_map_clock_reply,
+ subsystem_to_name_map_clock,
+ subsystem_to_name_map_exc,
+ subsystem_to_name_map_host_priv,
+ subsystem_to_name_map_host_security,
+ subsystem_to_name_map_lock_set,
+ subsystem_to_name_map_mach_host,
+ subsystem_to_name_map_mach_port,
+ subsystem_to_name_map_mach_vm,
+ subsystem_to_name_map_mach_voucher,
+ subsystem_to_name_map_memory_entry,
+ subsystem_to_name_map_processor_set,
+ subsystem_to_name_map_processor,
+ subsystem_to_name_map_task,
+ subsystem_to_name_map_thread_act,
+ subsystem_to_name_map_vm_map,
+};
+// clang-format on
+
+#define PRIME_NUMBER 8387
+char *mach_msg_name_table[PRIME_NUMBER] = {0};
+static int hash_mach_msg_num_to_ndx(int mach_msg_num) {
+ return mach_msg_num % PRIME_NUMBER;
+}
+static void mach_msg_id_hash_table_init() {
+ static bool initialized = false;
+ if (initialized == true) {
+ return;
+ }
+ initialized = true;
+
+ int count = sizeof(mach_msg_array) / sizeof(mach_msg_array[0]);
+ for (size_t i = 0; i < count; i++) {
+ mach_msg_entry_t entry = mach_msg_array[i];
+ int ndx = hash_mach_msg_num_to_ndx(entry.mach_msg_id);
+ mach_msg_name_table[ndx] = entry.mach_msg_name;
+ }
+}
+
+const char *mach_syscall_num_to_str(int num) {
+ return mach_syscall_name_table[0 - num];
+}
+
+char *mach_msg_id_to_str(int msgh_id) {
+ int ndx = hash_mach_msg_num_to_ndx(msgh_id);
+ return mach_msg_name_table[ndx];
+}
+
+char *mach_msg_to_str(mach_msg_header_t *msg) {
+ static mach_port_t self_port = MACH_PORT_NULL;
+
+ if (self_port == MACH_PORT_NULL) {
+ self_port = mach_task_self();
+ }
+
+ if (msg->msgh_remote_port == self_port) {
+ return mach_msg_id_to_str(msg->msgh_id);
+ }
+ return NULL;
+}
+
+static addr_t getCallFirstArg(DobbyRegisterContext *ctx) {
+ addr_t result;
+#if defined(_M_X64) || defined(__x86_64__)
+#if defined(_WIN32)
+ result = ctx->general.regs.rcx;
+#else
+ result = ctx->general.regs.rdi;
+#endif
+#elif defined(__arm64__) || defined(__aarch64__)
+ result = ctx->general.regs.x0;
+#elif defined(__arm__)
+ result = ctx->general.regs.r0;
+#else
+#error "Not Support Architecture."
+#endif
+ return result;
+}
+
+static addr_t getRealLr(DobbyRegisterContext *ctx) {
+ addr_t closure_trampoline_reserved_stack = ctx->sp - sizeof(addr_t);
+ return *(addr_t *)closure_trampoline_reserved_stack;
+}
+
+static addr_t fast_get_caller_from_main_binary(DobbyRegisterContext *ctx) {
+ static addr_t text_section_start = 0, text_section_end = 0;
+ static addr_t slide = 0;
+ if (text_section_start == 0 || text_section_end == 0) {
+ auto main = ProcessRuntimeUtility::GetProcessModule("mobilex");
+ addr_t main_header = (addr_t)main.load_address;
+
+ auto text_segment = macho_kit_get_segment_by_name((mach_header_t *)main_header, "__TEXT");
+ slide = main_header - text_segment->vmaddr;
+
+ auto text_section = macho_kit_get_section_by_name((mach_header_t *)main_header, "__TEXT", "__text");
+ text_section_start = main_header + (addr_t)text_section->offset;
+ text_section_end = text_section_start + text_section->size;
+ }
+
+ if (ctx == NULL)
+ return 0;
+
+ addr_t lr = getRealLr(ctx);
+ if (lr > text_section_start && lr < text_section_end)
+ return lr - slide;
+
+#define MAX_STACK_ITERATE_LEVEL 8
+ addr_t fp = ctx->fp;
+ if (fp == 0)
+ return 0;
+ for (int i = 0; i < MAX_STACK_ITERATE_LEVEL; i++) {
+ addr_t lr = *(addr_t *)(fp + sizeof(addr_t));
+ if (lr > text_section_start && lr < text_section_end)
+ return lr - slide;
+ fp = *(addr_t *)fp;
+ if (fp == 0)
+ return 0;
+ }
+ return 0;
+}
+
+static void mach_syscall_log_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) {
+ addr_t caller = fast_get_caller_from_main_binary(ctx);
+ if (caller == 0)
+ return;
+
+ char buffer[256] = {0};
+ int syscall_rum = ctx->general.regs.x16;
+ if (syscall_rum == -31) {
+ // mach_msg_trap
+ mach_msg_header_t *msg = (typeof(msg))getCallFirstArg(ctx);
+ char *mach_msg_name = mach_msg_to_str(msg);
+ if (mach_msg_name) {
+ sprintf(buffer, "[mach msg svc] %s\n", mach_msg_name);
+ } else {
+ buffer[0] = 0;
+ }
+ } else if (syscall_rum < 0) {
+ sprintf(buffer, "[mach svc-%d] %s\n", syscall_rum, mach_syscall_num_to_str(syscall_rum));
+ }
+ async_logger_print(buffer);
+}
+
+void supervisor_call_monitor_register_mach_syscall_call_log_handler() {
+ mach_msg_id_hash_table_init();
+ fast_get_caller_from_main_binary(NULL);
+ supervisor_call_monitor_register_handler(mach_syscall_log_handler);
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.cc
new file mode 100644
index 0000000..2a0a05b
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.cc
@@ -0,0 +1,44 @@
+#include "misc_utility.h"
+
+#include
+
+segment_command_t *macho_kit_get_segment_by_name(mach_header_t *header, const char *segname) {
+ segment_command_t *curr_seg_cmd = NULL;
+
+ curr_seg_cmd = (segment_command_t *)((addr_t)header + sizeof(mach_header_t));
+ for (int i = 0; i < header->ncmds; i++) {
+ if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) {
+ if (!strncmp(curr_seg_cmd->segname, segname, sizeof(curr_seg_cmd->segname))) {
+ break;
+ }
+ }
+ curr_seg_cmd = (segment_command_t *)((addr_t)curr_seg_cmd + curr_seg_cmd->cmdsize);
+ }
+
+ return curr_seg_cmd;
+}
+
+section_t *macho_kit_get_section_by_name(mach_header_t *header, const char *segname, const char *sectname) {
+ section_t *section = NULL;
+ segment_command_t *segment = NULL;
+
+ int i = 0;
+
+ segment = macho_kit_get_segment_by_name(header, segname);
+ if (!segment)
+ goto finish;
+
+ section = (section_t *)((addr_t)segment + sizeof(segment_command_t));
+ for (i = 0; i < segment->nsects; ++i) {
+ if (!strncmp(section->sectname, sectname, sizeof(section->sectname))) {
+ break;
+ }
+ section += 1;
+ }
+ if (i == segment->nsects) {
+ section = NULL;
+ }
+
+finish:
+ return section;
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.h b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.h
new file mode 100644
index 0000000..1c356c0
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/misc_utility.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include
+typedef uintptr_t addr_t;
+
+#include
+#include
+#include
+
+#if defined(__LP64__)
+typedef struct mach_header_64 mach_header_t;
+typedef struct segment_command_64 segment_command_t;
+typedef struct section_64 section_t;
+typedef struct nlist_64 nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64
+#else
+typedef struct mach_header mach_header_t;
+typedef struct segment_command segment_command_t;
+typedef struct section section_t;
+typedef struct nlist nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT
+#endif
+
+// get macho segment by segment name
+segment_command_t *macho_kit_get_segment_by_name(mach_header_t *mach_header, const char *segname);
+
+// get macho section by segment name and section name
+section_t *macho_kit_get_section_by_name(mach_header_t *mach_header, const char *segname, const char *sectname);
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/sensitive_api_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/sensitive_api_monitor.cc
new file mode 100644
index 0000000..6ab0765
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/sensitive_api_monitor.cc
@@ -0,0 +1,95 @@
+#include "dobby/dobby_internal.h"
+
+#include
+#include
+#include
+
+#include "SupervisorCallMonitor/supervisor_call_monitor.h"
+#include "misc-helper/async_logger.h"
+
+#define PT_DENY_ATTACH 31
+
+static void sensitive_api_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) {
+ char buffer[256] = {0};
+ int syscall_rum = ctx->general.regs.x16;
+ if (syscall_rum == 0) {
+ syscall_rum = (int)ctx->general.x[0];
+ if (syscall_rum == SYS_ptrace) {
+ int request = ctx->general.x[1];
+ if (request == PT_DENY_ATTACH) {
+ ctx->general.x[1] = 0;
+ // INFO_LOG("syscall svc ptrace deny");
+ }
+ }
+ if (syscall_rum == SYS_exit) {
+ // INFO_LOG("syscall svc exit");
+ }
+ } else if (syscall_rum > 0) {
+ if (syscall_rum == SYS_ptrace) {
+ int request = ctx->general.x[0];
+ if (request == PT_DENY_ATTACH) {
+ ctx->general.x[0] = 0;
+ // INFO_LOG("svc ptrace deny");
+ }
+ }
+ if (syscall_rum == SYS_exit) {
+ // INFO_LOG("svc exit");
+ }
+ }
+ async_logger_print(buffer);
+}
+
+static int get_func_svc_offset(addr_t func_addr) {
+ typedef int32_t arm64_instr_t;
+ for (int i = 0; i < 8; i++) {
+ arm64_instr_t *insn = (arm64_instr_t *)func_addr + i;
+ if (*insn == 0xd4001001) {
+ return i * sizeof(arm64_instr_t);
+ }
+ }
+ return 0;
+}
+
+#include
+__typeof(sysctl) *orig_sysctl;
+int fake_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
+ struct kinfo_proc *info = NULL;
+ int ret = orig_sysctl(name, namelen, oldp, oldlenp, newp, newlen);
+ if (name[0] == CTL_KERN && name[1] == KERN_PROC && name[2] == KERN_PROC_PID) {
+ info = (struct kinfo_proc *)oldp;
+ info->kp_proc.p_flag &= ~(P_TRACED);
+ }
+ return ret;
+}
+
+void supervisor_call_monitor_register_sensitive_api_handler() {
+ char *sensitive_func_array[] = {"ptrace", "exit"};
+ size_t count = sizeof(sensitive_func_array) / sizeof(char *);
+ for (size_t i = 0; i < count; i++) {
+
+ addr_t func_addr = 0;
+
+ char func_name[64] = {0};
+ sprintf(func_name, "__%s", sensitive_func_array[i]);
+ func_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", func_name);
+ if (func_addr == 0) {
+ func_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", sensitive_func_array[i]);
+ }
+ if (func_addr == 0) {
+ INFO_LOG("not found func %s", sensitive_func_array[i]);
+ continue;
+ }
+ int func_svc_offset = get_func_svc_offset(func_addr);
+ if (func_svc_offset == 0) {
+ INFO_LOG("not found svc %s", sensitive_func_array[i]);
+ continue;
+ }
+ addr_t func_svc_addr = func_addr + func_svc_offset;
+ supervisor_call_monitor_register_svc(func_svc_addr);
+ }
+
+ // ===============
+ DobbyHook((void *)sysctl, (void *)fake_sysctl, (void **)&orig_sysctl);
+
+ supervisor_call_monitor_register_handler(sensitive_api_handler);
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc
new file mode 100644
index 0000000..c97b111
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.cc
@@ -0,0 +1,138 @@
+#include "SupervisorCallMonitor/misc_utility.h"
+#include "dobby/dobby_internal.h"
+#include "PlatformUtil/ProcessRuntimeUtility.h"
+
+#include "misc-helper/async_logger.h"
+
+#include
+std::vector *g_supervisor_call_handlers;
+
+static const char *fast_get_main_app_bundle_udid() {
+ static char *main_app_bundle_udid = NULL;
+ if (main_app_bundle_udid)
+ return main_app_bundle_udid;
+
+ auto main = ProcessRuntimeUtility::GetProcessModuleMap()[0];
+ char main_binary_path[2048] = {0};
+ if (realpath(main.path, main_binary_path) == NULL)
+ return NULL;
+
+ char *bundle_udid_ndx = main_binary_path + strlen("/private/var/containers/Bundle/Application/");
+ main_app_bundle_udid = (char *)malloc(36 + 1);
+ strncpy(main_app_bundle_udid, bundle_udid_ndx, 36);
+ main_app_bundle_udid[36] = 0;
+ return main_app_bundle_udid;
+}
+
+static void common_supervisor_call_monitor_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) {
+ if (g_supervisor_call_handlers == NULL) {
+ return;
+ }
+ for (auto handler : *g_supervisor_call_handlers) {
+ handler(ctx, info);
+ }
+}
+
+void supervisor_call_monitor_register_handler(DBICallTy handler) {
+ if (g_supervisor_call_handlers == NULL) {
+ g_supervisor_call_handlers = new std::vector();
+ }
+ g_supervisor_call_handlers->push_back(handler);
+}
+
+std::vector *g_svc_addr_array;
+
+void supervisor_call_monitor_register_svc(addr_t svc_addr) {
+ if (g_svc_addr_array == NULL) {
+ g_svc_addr_array = new std::vector();
+ }
+
+ if (g_svc_addr_array) {
+ auto iter = g_svc_addr_array->begin();
+ for (; iter != g_svc_addr_array->end(); iter++) {
+ if (*iter == svc_addr)
+ return;
+ }
+ }
+
+ g_svc_addr_array->push_back(svc_addr);
+ DobbyInstrument((void *)svc_addr, common_supervisor_call_monitor_handler);
+ DLOG(2, "register supervisor_call_monitor at %p", svc_addr);
+}
+
+void supervisor_call_monitor_register_image(void *header) {
+ auto text_section = macho_kit_get_section_by_name((mach_header_t *)header, "__TEXT", "__text");
+
+ addr_t insn_addr = (addr_t)header + (addr_t)text_section->offset;
+ addr_t insn_addr_end = insn_addr + text_section->size;
+
+ for (; insn_addr < insn_addr_end; insn_addr += sizeof(uint32_t)) {
+ if (*(uint32_t *)insn_addr == 0xd4001001) {
+ supervisor_call_monitor_register_svc((addr_t)insn_addr);
+ }
+ }
+}
+
+void supervisor_call_monitor_register_main_app() {
+ const char *main_bundle_udid = fast_get_main_app_bundle_udid();
+ auto module_map = ProcessRuntimeUtility::GetProcessModuleMap();
+ for (auto module : module_map) {
+ if (strstr(module.path, main_bundle_udid)) {
+ INFO_LOG("[supervisor_call_monitor] %s", module.path);
+ supervisor_call_monitor_register_image((void *)module.load_address);
+ }
+ }
+}
+
+extern "C" int __shared_region_check_np(uint64_t *startaddress);
+
+struct dyld_cache_header *shared_cache_get_load_addr() {
+ static struct dyld_cache_header *shared_cache_load_addr = 0;
+ if (shared_cache_load_addr)
+ return shared_cache_load_addr;
+#if 0
+ if (syscall(294, &shared_cache_load_addr) == 0) {
+#else
+ // FIXME:
+ if (__shared_region_check_np((uint64_t *)&shared_cache_load_addr) != 0) {
+#endif
+ shared_cache_load_addr = 0;
+}
+return shared_cache_load_addr;
+}
+void supervisor_call_monitor_register_system_kernel() {
+ auto libsystem = ProcessRuntimeUtility::GetProcessModule("libsystem_kernel.dylib");
+ addr_t libsystem_header = (addr_t)libsystem.load_address;
+ auto text_section = macho_kit_get_section_by_name((mach_header_t *)libsystem_header, "__TEXT", "__text");
+
+ addr_t shared_cache_load_addr = (addr_t)shared_cache_get_load_addr();
+ addr_t insn_addr = shared_cache_load_addr + (addr_t)text_section->offset;
+ addr_t insn_addr_end = insn_addr + text_section->size;
+
+ addr_t write_svc_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", "write");
+ write_svc_addr += 4;
+
+ addr_t __psynch_mutexwait_svc_addr = (addr_t)DobbySymbolResolver("libsystem_kernel.dylib", "__psynch_mutexwait");
+ __psynch_mutexwait_svc_addr += 4;
+
+ for (; insn_addr < insn_addr_end; insn_addr += sizeof(uint32_t)) {
+ if (*(uint32_t *)insn_addr == 0xd4001001) {
+ if (insn_addr == write_svc_addr)
+ continue;
+
+ if (insn_addr == __psynch_mutexwait_svc_addr)
+ continue;
+ supervisor_call_monitor_register_svc((addr_t)insn_addr);
+ }
+ }
+}
+
+void supervisor_call_monitor_init() {
+ // create logger file
+ char logger_path[1024] = {0};
+ sprintf(logger_path, "%s%s", getenv("HOME"), "/Documents/svc_monitor.txt");
+ INFO_LOG("HOME: %s", logger_path);
+ async_logger_init(logger_path);
+
+ dobby_enable_near_branch_trampoline();
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.h b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.h
new file mode 100644
index 0000000..45bde0a
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/supervisor_call_monitor.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include
+typedef uintptr_t addr_t;
+
+#include "dobby.h"
+
+void supervisor_call_monitor_init();
+
+void supervisor_call_monitor_register_handler(DBICallTy handler);
+
+void supervisor_call_monitor_register_svc(addr_t svc_addr);
+
+void supervisor_call_monitor_register_image(void *header);
+
+void supervisor_call_monitor_register_main_app();
+
+void supervisor_call_monitor_register_system_kernel();
+
+void supervisor_call_monitor_register_syscall_call_log_handler();
+
+void supervisor_call_monitor_register_mach_syscall_call_log_handler();
+
+void supervisor_call_monitor_register_sensitive_api_handler();
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/system_call_log_handler.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/system_call_log_handler.cc
new file mode 100644
index 0000000..d1ca013
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/system_call_log_handler.cc
@@ -0,0 +1,98 @@
+#include "dobby/dobby_internal.h"
+
+#include
+
+#include "misc-helper/async_logger.h"
+#include "PlatformUtil/ProcessRuntimeUtility.h"
+#include "SupervisorCallMonitor/misc_utility.h"
+#include "SupervisorCallMonitor/supervisor_call_monitor.h"
+
+#include "XnuInternal/syscalls.c"
+
+static const char *syscall_num_to_str(int num) {
+ return syscallnames[num];
+}
+
+static addr_t getCallFirstArg(DobbyRegisterContext *ctx) {
+ addr_t result;
+#if defined(_M_X64) || defined(__x86_64__)
+#if defined(_WIN32)
+ result = ctx->general.regs.rcx;
+#else
+ result = ctx->general.regs.rdi;
+#endif
+#elif defined(__arm64__) || defined(__aarch64__)
+ result = ctx->general.regs.x0;
+#elif defined(__arm__)
+ result = ctx->general.regs.r0;
+#else
+#error "Not Support Architecture."
+#endif
+ return result;
+}
+
+static addr_t getRealLr(DobbyRegisterContext *ctx) {
+ addr_t closure_trampoline_reserved_stack = ctx->sp - sizeof(addr_t);
+ return *(addr_t *)closure_trampoline_reserved_stack;
+}
+
+static addr_t fast_get_caller_from_main_binary(DobbyRegisterContext *ctx) {
+ static addr_t text_section_start = 0, text_section_end = 0;
+ static addr_t slide = 0;
+ if (text_section_start == 0 || text_section_end == 0) {
+ auto main = ProcessRuntimeUtility::GetProcessModule("");
+ addr_t main_header = (addr_t)main.load_address;
+
+ auto text_segment = macho_kit_get_segment_by_name((mach_header_t *)main_header, "__TEXT");
+ slide = main_header - text_segment->vmaddr;
+
+ auto text_section = macho_kit_get_section_by_name((mach_header_t *)main_header, "__TEXT", "__text");
+ text_section_start = main_header + (addr_t)text_section->offset;
+ text_section_end = text_section_start + text_section->size;
+ }
+
+ if (ctx == NULL)
+ return 0;
+
+ addr_t lr = getRealLr(ctx);
+ if (lr > text_section_start && lr < text_section_end)
+ return lr - slide;
+
+#define MAX_STACK_ITERATE_LEVEL 8
+ addr_t fp = ctx->fp;
+ if (fp == 0)
+ return 0;
+ for (int i = 0; i < MAX_STACK_ITERATE_LEVEL; i++) {
+ addr_t lr = *(addr_t *)(fp + sizeof(addr_t));
+ if (lr > text_section_start && lr < text_section_end)
+ return lr - slide;
+ fp = *(addr_t *)fp;
+ if (fp == 0)
+ return 0;
+ }
+ return 0;
+}
+
+static void syscall_log_handler(DobbyRegisterContext *ctx, const InterceptEntry *info) {
+ addr_t caller = fast_get_caller_from_main_binary(ctx);
+ if (caller == 0)
+ return;
+
+ char buffer[2048] = {0};
+ int syscall_rum = ctx->general.regs.x16;
+ if (syscall_rum == 0) {
+ syscall_rum = (int)getCallFirstArg(ctx);
+ sprintf(buffer, "[syscall svc-%d] %s\n", syscall_rum, syscall_num_to_str(syscall_rum));
+ } else if (syscall_rum > 0) {
+ sprintf(buffer, "[svc-%d] %s\n", syscall_rum, syscall_num_to_str(syscall_rum));
+ if (syscall_rum == 5) {
+ sprintf(buffer, "[svc-%d] %s:%s\n", syscall_rum, syscall_num_to_str(syscall_rum), (char *)ctx->general.regs.x0);
+ }
+ }
+ async_logger_print(buffer);
+}
+
+void supervisor_call_monitor_register_syscall_call_log_handler() {
+ fast_get_caller_from_main_binary(NULL);
+ supervisor_call_monitor_register_handler(syscall_log_handler);
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/test_supervisor_call_monitor.cc b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/test_supervisor_call_monitor.cc
new file mode 100644
index 0000000..394a8c8
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SupervisorCallMonitor/test_supervisor_call_monitor.cc
@@ -0,0 +1,16 @@
+
+#include "dobby/dobby_internal.h"
+
+#include "SupervisorCallMonitor/supervisor_call_monitor.h"
+
+#if 1
+__attribute__((constructor)) static void ctor() {
+ log_set_level(2);
+ log_switch_to_syslog();
+
+ supervisor_call_monitor_init();
+ supervisor_call_monitor_register_main_app();
+ supervisor_call_monitor_register_syscall_call_log_handler();
+ supervisor_call_monitor_register_mach_syscall_call_log_handler();
+}
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/CMakeLists.txt b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/CMakeLists.txt
new file mode 100644
index 0000000..6528592
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/CMakeLists.txt
@@ -0,0 +1,55 @@
+set(SOURCE_FILE_LIST)
+
+include_directories(
+ .
+)
+
+if (NOT DEFINED DOBBY_DIR)
+ message(FATAL_ERROR "DOBBY_DIR must be set!")
+endif ()
+
+if (SYSTEM.Darwin)
+ add_library(macho_ctx_kit
+ ${CMAKE_CURRENT_SOURCE_DIR}/macho/macho_ctx.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/macho/macho_ctx.cc
+ )
+
+ add_library(shared_cache_ctx_kit
+ ${CMAKE_CURRENT_SOURCE_DIR}/macho/shared_cache_ctx.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/macho/shared_cache_ctx.cpp
+ )
+
+ set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST}
+ macho/macho_ctx.cc
+ macho/dobby_symbol_resolver.cc
+ )
+
+ if (NOT DOBBY_BUILD_KERNEL_MODE)
+ set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST}
+ macho/macho_file_symbol_resolver.cpp
+ macho/shared_cache_ctx.cpp
+ ${DOBBY_DIR}/source/Backend/UserMode/PlatformUtil/Darwin/ProcessRuntimeUtility.cc
+ )
+ endif ()
+elseif (SYSTEM.Linux OR SYSTEM.Android)
+ set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST}
+ elf/dobby_symbol_resolver.cc
+
+ ${DOBBY_DIR}/source/Backend/UserMode/PlatformUtil/Linux/ProcessRuntimeUtility.cc
+ )
+elseif (SYSTEM.Windows)
+ set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST}
+ pe/dobby_symbol_resolver.cc
+
+ ${DOBBY_DIR}/source/Backend/UserMode/PlatformUtil/Windows/ProcessRuntimeUtility.cc
+ )
+endif ()
+
+get_absolute_path_list(SOURCE_FILE_LIST SOURCE_FILE_LIST_)
+set(SOURCE_FILE_LIST ${SOURCE_FILE_LIST_})
+
+add_library(dobby_symbol_resolver
+ ${SOURCE_FILE_LIST}
+ )
+
+
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/dobby_symbol_resolver.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/dobby_symbol_resolver.h
new file mode 100644
index 0000000..22dee3c
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/dobby_symbol_resolver.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#if defined(BUILDING_INTERNAL)
+#include "macho/dobby_symbol_resolver_priv.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *DobbySymbolResolver(const char *image_name, const char *symbol_name);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/elf/dobby_symbol_resolver.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/elf/dobby_symbol_resolver.cc
new file mode 100644
index 0000000..bf45ea9
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/elf/dobby_symbol_resolver.cc
@@ -0,0 +1,238 @@
+#include "SymbolResolver/dobby_symbol_resolver.h"
+#include "dobby/common.h"
+
+#include
+#include
+#include
+#include
+
+#include "mmap_file_util.h"
+
+#include "PlatformUtil/ProcessRuntimeUtility.h"
+
+#include
+
+#undef LOG_TAG
+#define LOG_TAG "DobbySymbolResolver"
+
+typedef struct elf_ctx {
+ void *header;
+
+ uintptr_t load_bias;
+
+ ElfW(Shdr) * sym_sh_;
+ ElfW(Shdr) * dynsym_sh_;
+
+ const char *strtab_;
+ ElfW(Sym) * symtab_;
+
+ const char *dynstrtab_;
+ ElfW(Sym) * dynsymtab_;
+
+ size_t nbucket_;
+ size_t nchain_;
+ uint32_t *bucket_;
+ uint32_t *chain_;
+
+ size_t gnu_nbucket_;
+ uint32_t *gnu_bucket_;
+ uint32_t *gnu_chain_;
+ uint32_t gnu_maskwords_;
+ uint32_t gnu_shift2_;
+ ElfW(Addr) * gnu_bloom_filter_;
+} elf_ctx_t;
+
+static void get_syms(ElfW(Ehdr) * header, ElfW(Sym) * *symtab_ptr, char **strtab_ptr, int *count_ptr) {
+ ElfW(Shdr) *section_header = NULL;
+ section_header = (ElfW(Shdr) *)((addr_t)header + header->e_shoff);
+
+ ElfW(Shdr) *section_strtab_section_header = NULL;
+ section_strtab_section_header = (ElfW(Shdr) *)((addr_t)section_header + header->e_shstrndx * header->e_shentsize);
+ char *section_strtab = NULL;
+ section_strtab = (char *)((addr_t)header + section_strtab_section_header->sh_offset);
+
+ for (int i = 0; i < header->e_shnum; ++i) {
+ const char *section_name = (const char *)(section_strtab + section_header->sh_name);
+ if (section_header->sh_type == SHT_SYMTAB && strcmp(section_name, ".symtab") == 0) {
+ *symtab_ptr = (ElfW(Sym) *)((addr_t)header + section_header->sh_offset);
+ *count_ptr = section_header->sh_size / sizeof(ElfW(Sym));
+ }
+
+ if (section_header->sh_type == SHT_STRTAB && strcmp(section_name, ".strtab") == 0) {
+ *strtab_ptr = (char *)((addr_t)header + section_header->sh_offset);
+ }
+ section_header = (ElfW(Shdr) *)((addr_t)section_header + header->e_shentsize);
+ }
+}
+
+int elf_ctx_init(elf_ctx_t *ctx, void *header_) {
+ ElfW(Ehdr) *ehdr = (ElfW(Ehdr) *)header_;
+ ctx->header = ehdr;
+
+ ElfW(Addr) ehdr_addr = (ElfW(Addr))ehdr;
+
+ // Handle dynamic segment
+ {
+ ElfW(Addr) addr = 0;
+ ElfW(Dyn) *dyn = NULL;
+ ElfW(Phdr) *phdr = reinterpret_cast(ehdr_addr + ehdr->e_phoff);
+ for (size_t i = 0; i < ehdr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_DYNAMIC) {
+ dyn = reinterpret_cast(ehdr_addr + phdr[i].p_offset);
+ } else if (phdr[i].p_type == PT_LOAD) {
+ addr = ehdr_addr + phdr[i].p_offset - phdr[i].p_vaddr;
+ if (ctx->load_bias == 0)
+ ctx->load_bias = ehdr_addr - (phdr[i].p_vaddr - phdr[i].p_offset);
+ } else if (phdr[i].p_type == PT_PHDR) {
+ ctx->load_bias = (ElfW(Addr))phdr - phdr[i].p_vaddr;
+ }
+ }
+// ctx->load_bias =
+#if 0
+ const char *strtab = nullptr;
+ ElfW(Sym) *symtab = nullptr;
+ for (ElfW(Dyn) *d = dyn; d->d_tag != DT_NULL; ++d) {
+ if (d->d_tag == DT_STRTAB) {
+ strtab = reinterpret_cast(addr + d->d_un.d_ptr);
+ } else if (d->d_tag == DT_SYMTAB) {
+ symtab = reinterpret_cast(addr + d->d_un.d_ptr);
+ }
+ }
+#endif
+ }
+
+ // Handle section
+ {
+ ElfW(Shdr) * dynsym_sh, *dynstr_sh;
+ ElfW(Shdr) * sym_sh, *str_sh;
+
+ ElfW(Shdr) *shdr = reinterpret_cast(ehdr_addr + ehdr->e_shoff);
+
+ ElfW(Shdr) *shstr_sh = NULL;
+ shstr_sh = &shdr[ehdr->e_shstrndx];
+ char *shstrtab = NULL;
+ shstrtab = (char *)((addr_t)ehdr_addr + shstr_sh->sh_offset);
+
+ for (size_t i = 0; i < ehdr->e_shnum; i++) {
+ if (shdr[i].sh_type == SHT_SYMTAB) {
+ sym_sh = &shdr[i];
+ ctx->sym_sh_ = sym_sh;
+ ctx->symtab_ = (ElfW(Sym) *)(ehdr_addr + shdr[i].sh_offset);
+ } else if (shdr[i].sh_type == SHT_STRTAB && strcmp(shstrtab + shdr[i].sh_name, ".strtab") == 0) {
+ str_sh = &shdr[i];
+ ctx->strtab_ = (const char *)(ehdr_addr + shdr[i].sh_offset);
+ } else if (shdr[i].sh_type == SHT_DYNSYM) {
+ dynsym_sh = &shdr[i];
+ ctx->dynsym_sh_ = dynsym_sh;
+ ctx->dynsymtab_ = (ElfW(Sym) *)(ehdr_addr + shdr[i].sh_offset);
+ } else if (shdr[i].sh_type == SHT_STRTAB && strcmp(shstrtab + shdr[i].sh_name, ".dynstr") == 0) {
+ dynstr_sh = &shdr[i];
+ ctx->dynstrtab_ = (const char *)(ehdr_addr + shdr[i].sh_offset);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void *iterate_symbol_table_impl(const char *symbol_name, ElfW(Sym) * symtab, const char *strtab, int count) {
+ for (int i = 0; i < count; ++i) {
+ ElfW(Sym) *sym = symtab + i;
+ const char *symbol_name_ = strtab + sym->st_name;
+ if (strcmp(symbol_name_, symbol_name) == 0) {
+ return (void *)sym->st_value;
+ }
+ }
+ return NULL;
+}
+
+void *elf_ctx_iterate_symbol_table(elf_ctx_t *ctx, const char *symbol_name) {
+ void *result = NULL;
+ if (ctx->symtab_ && ctx->strtab_) {
+ size_t count = ctx->sym_sh_->sh_size / sizeof(ElfW(Sym));
+ result = iterate_symbol_table_impl(symbol_name, ctx->symtab_, ctx->strtab_, count);
+ if (result)
+ return result;
+ }
+
+ if (ctx->dynsymtab_ && ctx->dynstrtab_) {
+ size_t count = ctx->dynsym_sh_->sh_size / sizeof(ElfW(Sym));
+ result = iterate_symbol_table_impl(symbol_name, ctx->dynsymtab_, ctx->dynstrtab_, count);
+ if (result)
+ return result;
+ }
+ return NULL;
+}
+
+void *resolve_elf_internal_symbol(const char *library_name, const char *symbol_name) {
+ void *result = NULL;
+
+ if (library_name) {
+ RuntimeModule module = ProcessRuntimeUtility::GetProcessModule(library_name);
+
+ if (module.load_address) {
+ auto mmapFileMng = MmapFileManager(module.path);
+ auto file_mem = mmapFileMng.map();
+
+ elf_ctx_t ctx;
+ memset(&ctx, 0, sizeof(elf_ctx_t));
+ if (file_mem) {
+ elf_ctx_init(&ctx, file_mem);
+ result = elf_ctx_iterate_symbol_table(&ctx, symbol_name);
+ }
+
+ if (result)
+ result = (void *)((addr_t)result + (addr_t)module.load_address - ((addr_t)file_mem - (addr_t)ctx.load_bias));
+ }
+ }
+
+ if (!result) {
+ auto ProcessModuleMap = ProcessRuntimeUtility::GetProcessModuleMap();
+ for (auto module : ProcessModuleMap) {
+
+ if (module.load_address) {
+ auto mmapFileMng = MmapFileManager(module.path);
+ auto file_mem = mmapFileMng.map();
+
+ elf_ctx_t ctx;
+ memset(&ctx, 0, sizeof(elf_ctx_t));
+ if (file_mem) {
+ elf_ctx_init(&ctx, file_mem);
+ result = elf_ctx_iterate_symbol_table(&ctx, symbol_name);
+ }
+
+ if (result)
+ result = (void *)((addr_t)result + (addr_t)module.load_address - ((addr_t)file_mem - (addr_t)ctx.load_bias));
+ }
+
+ if (result)
+ break;
+ }
+ }
+ return result;
+}
+
+// impl at "android_restriction.cc"
+extern std::vector linker_get_solist();
+
+PUBLIC void *DobbySymbolResolver(const char *image_name, const char *symbol_name_pattern) {
+ void *result = NULL;
+
+#if 0
+ auto solist = linker_get_solist();
+ for (auto soinfo : solist) {
+ uintptr_t handle = linker_soinfo_to_handle(soinfo);
+ if (image_name == NULL || strstr(linker_soinfo_get_realpath(soinfo), image_name) != 0) {
+ result = dlsym((void *)handle, symbol_name_pattern);
+ if (result)
+ return result;
+ }
+ }
+#endif
+ result = dlsym(RTLD_DEFAULT, symbol_name_pattern);
+ if (result)
+ return result;
+
+ result = resolve_elf_internal_symbol(image_name, symbol_name_pattern);
+ return result;
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver.cc
new file mode 100644
index 0000000..bd5c993
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver.cc
@@ -0,0 +1,114 @@
+#include "dobby_symbol_resolver.h"
+#include "macho/dobby_symbol_resolver_priv.h"
+#include "macho_file_symbol_resolver.h"
+
+#include "dobby/common.h"
+
+#include
+#include
+
+#include "PlatformUtil/ProcessRuntimeUtility.h"
+
+#include "macho_ctx.h"
+#include "shared_cache_ctx.h"
+
+#if !defined(BUILDING_KERNEL)
+#include
+#include
+#endif
+
+#undef LOG_TAG
+#define LOG_TAG "DobbySymbolResolver"
+
+PUBLIC void *DobbySymbolResolver(const char *image_name, const char *symbol_name_pattern) {
+ uintptr_t result = 0;
+ auto modules = ProcessRuntimeUtility::GetProcessModuleMap();
+
+ for (auto iter = modules.begin(); iter != modules.end(); iter++) {
+ auto module = *iter;
+
+ // image filter
+ if (image_name && !strstr(module.path, image_name))
+ continue;
+
+ // dyld in shared cached at new os version
+ // ignore dyld, as some functions as own implementation in dyld
+ if (!image_name && strstr(module.path, "dyld"))
+ continue;
+
+ auto header = (mach_header_t *)module.load_address;
+ if (header == nullptr)
+ continue;
+
+#if 0
+ DEBUG_LOG("resolve image: %s", module.path);
+#endif
+
+ nlist_t *symtab = NULL;
+ uint32_t symtab_count = 0;
+ char *strtab = NULL;
+
+#if !defined(BUILDING_KERNEL)
+#if defined(__arm__) || defined(__aarch64__)
+ static int shared_cache_ctx_init_once = 0;
+ static shared_cache_ctx_t shared_cache_ctx;
+ if (shared_cache_ctx_init_once == 0) {
+ shared_cache_ctx_init_once = 1;
+ shared_cache_ctx_init(&shared_cache_ctx);
+ shared_cache_load_symbols(&shared_cache_ctx);
+ }
+ if (shared_cache_ctx.mmap_shared_cache) {
+ // shared cache library
+ if (shared_cache_is_contain(&shared_cache_ctx, (addr_t)header, 0)) {
+ shared_cache_get_symbol_table(&shared_cache_ctx, header, &symtab, &symtab_count, &strtab);
+ }
+ }
+ if (symtab && strtab) {
+ result = macho_iterate_symbol_table((char *)symbol_name_pattern, symtab, symtab_count, strtab);
+ }
+ if (result) {
+ result = result + shared_cache_ctx.runtime_slide;
+ return (void *)result;
+ }
+#endif
+#endif
+
+ macho_ctx_t macho_ctx(header);
+ result = macho_ctx.symbol_resolve(symbol_name_pattern);
+ if (result) {
+ return (void *)result;
+ }
+ }
+
+#if !defined(BUILDING_KERNEL)
+ mach_header_t *dyld_header = NULL;
+ if (image_name != NULL && strcmp(image_name, "dyld") == 0) {
+ // task info
+ task_dyld_info_data_t task_dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ if (task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count)) {
+ return NULL;
+ }
+
+ // get dyld load address
+ const struct dyld_all_image_infos *infos =
+ (struct dyld_all_image_infos *)(uintptr_t)task_dyld_info.all_image_info_addr;
+ dyld_header = (mach_header_t *)infos->dyldImageLoadAddress;
+ macho_ctx_t dyld_ctx(dyld_header);
+ result = dyld_ctx.symbol_resolve(symbol_name_pattern);
+
+ bool is_dyld_in_cache = ((mach_header_t *)dyld_header)->flags & MH_DYLIB_IN_CACHE;
+ if (!is_dyld_in_cache && result == 0) {
+ result = macho_file_symbol_resolve(dyld_header->cputype, dyld_header->cpusubtype, "/usr/lib/dyld",
+ (char *)symbol_name_pattern);
+ result += (uintptr_t)dyld_header;
+ }
+ }
+#endif
+
+ if (result == 0) {
+ DEBUG_LOG("symbol resolver failed: %s", symbol_name_pattern);
+ }
+
+ return (void *)result;
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver_priv.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver_priv.h
new file mode 100644
index 0000000..c6b4244
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/dobby_symbol_resolver_priv.h
@@ -0,0 +1,6 @@
+#include
+#include
+#include
+
+#include "macho_ctx.h"
+
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.cc
new file mode 100644
index 0000000..92188ea
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.cc
@@ -0,0 +1,358 @@
+#include "macho_ctx.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#define ASSERT(x)
+
+uintptr_t macho_iterate_symbol_table(char *symbol_name_pattern, nlist_t *symtab, uint32_t symtab_count, char *strtab) {
+ for (uint32_t i = 0; i < symtab_count; i++) {
+ if (symtab[i].n_value) {
+ uint32_t strtab_offset = symtab[i].n_un.n_strx;
+ char *symbol_name = strtab + strtab_offset;
+#if 0
+ printf("> %s", symbol_name);
+#endif
+ if (strcmp(symbol_name_pattern, symbol_name) == 0) {
+ return symtab[i].n_value;
+ }
+ if (symbol_name[0] == '_') {
+ if (strcmp(symbol_name_pattern, &symbol_name[1]) == 0) {
+ return symtab[i].n_value;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+// ---
+
+void macho_ctx_t::init(mach_header_t *header, bool is_runtime_mode) {
+ memset(this, 0, sizeof(macho_ctx_t));
+
+ this->is_runtime_mode = is_runtime_mode;
+
+ this->header = header;
+ segment_command_t *curr_seg_cmd;
+ segment_command_t *text_segment = 0, *text_exec_segment = 0, *data_segment = 0, *data_const_segment = 0,
+ *linkedit_segment = 0;
+ struct symtab_command *symtab_cmd = 0;
+ struct dysymtab_command *dysymtab_cmd = 0;
+ struct dyld_info_command *dyld_info_cmd = 0;
+ struct linkedit_data_command *exports_trie_cmd = 0;
+ struct linkedit_data_command *chained_fixups_cmd = NULL;
+
+ curr_seg_cmd = (segment_command_t *)((uintptr_t)header + sizeof(mach_header_t));
+ for (int i = 0; i < header->ncmds; i++) {
+ if (curr_seg_cmd->cmd == LC_SEGMENT_ARCH_DEPENDENT) {
+ // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB and REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
+ this->segments[this->segments_count++] = curr_seg_cmd;
+
+ if (strcmp(curr_seg_cmd->segname, "__LINKEDIT") == 0) {
+ linkedit_segment = curr_seg_cmd;
+ } else if (strcmp(curr_seg_cmd->segname, "__DATA") == 0) {
+ data_segment = curr_seg_cmd;
+ } else if (strcmp(curr_seg_cmd->segname, "__DATA_CONST") == 0) {
+ data_const_segment = curr_seg_cmd;
+ } else if (strcmp(curr_seg_cmd->segname, "__TEXT") == 0) {
+ text_segment = curr_seg_cmd;
+ } else if (strcmp(curr_seg_cmd->segname, "__TEXT_EXEC") == 0) {
+ text_exec_segment = curr_seg_cmd;
+ }
+ } else if (curr_seg_cmd->cmd == LC_SYMTAB) {
+ symtab_cmd = (struct symtab_command *)curr_seg_cmd;
+ } else if (curr_seg_cmd->cmd == LC_DYSYMTAB) {
+ dysymtab_cmd = (struct dysymtab_command *)curr_seg_cmd;
+ } else if (curr_seg_cmd->cmd == LC_DYLD_INFO || curr_seg_cmd->cmd == LC_DYLD_INFO_ONLY) {
+ dyld_info_cmd = (struct dyld_info_command *)curr_seg_cmd;
+ } else if (curr_seg_cmd->cmd == LC_DYLD_EXPORTS_TRIE) {
+ exports_trie_cmd = (struct linkedit_data_command *)curr_seg_cmd;
+ } else if (curr_seg_cmd->cmd == LC_DYLD_CHAINED_FIXUPS) {
+ chained_fixups_cmd = (struct linkedit_data_command *)curr_seg_cmd;
+ }
+ curr_seg_cmd = (segment_command_t *)((uintptr_t)curr_seg_cmd + curr_seg_cmd->cmdsize);
+ }
+
+ uintptr_t slide = (uintptr_t)header - (uintptr_t)text_segment->vmaddr;
+ uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff;
+ if (!is_runtime_mode) {
+ // as mmap, all segment is close
+ uintptr_t linkedit_segment_vmaddr = linkedit_segment->fileoff;
+ linkedit_base = (uintptr_t)slide + linkedit_segment_vmaddr - linkedit_segment->fileoff;
+ }
+
+ vm_region_start = segments[0]->vmaddr;
+ // skip __LINKEDIT
+ if (strcmp(segments[0]->segname, "__LINKEDIT") == 0) {
+ vm_region_start = segments[1]->vmaddr;
+ }
+ vm_region_end = segments[segments_count - 1]->vmaddr + segments[segments_count - 1]->vmsize;
+ vmaddr = vm_region_start;
+ vmsize = vm_region_end - vm_region_start;
+
+ this->text_seg = text_segment;
+ this->text_exec_seg = text_exec_segment;
+ this->data_seg = data_segment;
+ this->data_const_seg = data_const_segment;
+ this->linkedit_seg = linkedit_segment;
+
+ this->symtab_cmd = symtab_cmd;
+ this->dysymtab_cmd = dysymtab_cmd;
+ this->dyld_info_cmd = dyld_info_cmd;
+ this->exports_trie_cmd = exports_trie_cmd;
+ this->chained_fixups_cmd = chained_fixups_cmd;
+
+ this->slide = slide;
+ this->linkedit_base = linkedit_base;
+
+ this->symtab = (nlist_t *)(this->linkedit_base + this->symtab_cmd->symoff);
+ this->strtab = (char *)(this->linkedit_base + this->symtab_cmd->stroff);
+ this->indirect_symtab = (uint32_t *)(this->linkedit_base + this->dysymtab_cmd->indirectsymoff);
+}
+
+uintptr_t macho_ctx_t::iterate_symbol_table(const char *symbol_name_pattern) {
+ nlist_t *symtab = this->symtab;
+ uint32_t symtab_count = this->symtab_cmd->nsyms;
+ char *strtab = this->strtab;
+
+ for (uint32_t i = 0; i < symtab_count; i++) {
+ if (symtab[i].n_value) {
+ uint32_t strtab_offset = symtab[i].n_un.n_strx;
+ char *symbol_name = strtab + strtab_offset;
+#if 0
+ printf("> %s", symbol_name);
+#endif
+ if (strcmp(symbol_name_pattern, symbol_name) == 0) {
+ return symtab[i].n_value;
+ }
+ if (symbol_name[0] == '_') {
+ if (strcmp(symbol_name_pattern, &symbol_name[1]) == 0) {
+ return symtab[i].n_value;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+uintptr_t read_uleb128(const uint8_t **pp, const uint8_t *end) {
+ uint8_t *p = (uint8_t *)*pp;
+ uint64_t result = 0;
+ int bit = 0;
+ do {
+ if (p == end)
+ ASSERT(p == end);
+
+ uint64_t slice = *p & 0x7f;
+
+ if (bit > 63)
+ ASSERT(bit > 63);
+ else {
+ result |= (slice << bit);
+ bit += 7;
+ }
+ } while (*p++ & 0x80);
+
+ *pp = p;
+
+ return (uintptr_t)result;
+}
+
+intptr_t read_sleb128(const uint8_t **pp, const uint8_t *end) {
+ uint8_t *p = (uint8_t *)*pp;
+
+ int64_t result = 0;
+ int bit = 0;
+ uint8_t byte;
+ do {
+ if (p == end)
+ ASSERT(p == end);
+ byte = *p++;
+ result |= (((int64_t)(byte & 0x7f)) << bit);
+ bit += 7;
+ } while (byte & 0x80);
+ // sign extend negative numbers
+ if ((byte & 0x40) != 0)
+ result |= (~0ULL) << bit;
+
+ *pp = p;
+
+ return (intptr_t)result;
+}
+
+// dyld
+// bool MachOLoaded::findExportedSymbol
+// MachOLoaded::trieWalk
+uint8_t *tail_walk(const uint8_t *start, const uint8_t *end, const char *symbol) {
+ uint32_t visitedNodeOffsets[128];
+ int visitedNodeOffsetCount = 0;
+ visitedNodeOffsets[visitedNodeOffsetCount++] = 0;
+ const uint8_t *p = start;
+ while (p < end) {
+ uint64_t terminalSize = *p++;
+ if (terminalSize > 127) {
+ // except for re-export-with-rename, all terminal sizes fit in one byte
+ --p;
+ terminalSize = read_uleb128(&p, end);
+ }
+ if ((*symbol == '\0') && (terminalSize != 0)) {
+ return (uint8_t *)p;
+ }
+ const uint8_t *children = p + terminalSize;
+ if (children > end) {
+ // diag.error("malformed trie node, terminalSize=0x%llX extends past end of trie\n", terminalSize);
+ return NULL;
+ }
+ uint8_t childrenRemaining = *children++;
+ p = children;
+ uint64_t nodeOffset = 0;
+
+ for (; childrenRemaining > 0; --childrenRemaining) {
+ const char *ss = symbol;
+ bool wrongEdge = false;
+ // scan whole edge to get to next edge
+ // if edge is longer than target symbol name, don't read past end of symbol name
+ char c = *p;
+ while (c != '\0') {
+ if (!wrongEdge) {
+ if (c != *ss)
+ wrongEdge = true;
+ ++ss;
+ }
+ ++p;
+ c = *p;
+ }
+ if (wrongEdge) {
+ // advance to next child
+ ++p; // skip over zero terminator
+ // skip over uleb128 until last byte is found
+ while ((*p & 0x80) != 0)
+ ++p;
+ ++p; // skip over last byte of uleb128
+ if (p > end) {
+ // diag.error("malformed trie node, child node extends past end of trie\n");
+ return nullptr;
+ }
+ } else {
+ // the symbol so far matches this edge (child)
+ // so advance to the child's node
+ ++p;
+ nodeOffset = read_uleb128(&p, end);
+ if ((nodeOffset == 0) || (&start[nodeOffset] > end)) {
+ // diag.error("malformed trie child, nodeOffset=0x%llX out of range\n", nodeOffset);
+ return nullptr;
+ }
+ symbol = ss;
+ break;
+ }
+ }
+
+ if (nodeOffset != 0) {
+ if (nodeOffset > (uint64_t)(end - start)) {
+ // diag.error("malformed trie child, nodeOffset=0x%llX out of range\n", nodeOffset);
+ return NULL;
+ }
+ for (int i = 0; i < visitedNodeOffsetCount; ++i) {
+ if (visitedNodeOffsets[i] == nodeOffset) {
+ // diag.error("malformed trie child, cycle to nodeOffset=0x%llX\n", nodeOffset);
+ return NULL;
+ }
+ }
+ visitedNodeOffsets[visitedNodeOffsetCount++] = (uint32_t)nodeOffset;
+ p = &start[nodeOffset];
+ } else
+ p = end;
+ }
+ return NULL;
+}
+
+uintptr_t macho_ctx_t::iterate_exported_symbol(const char *symbol_name, uint64_t *out_flags) {
+ if (this->text_seg == NULL || this->linkedit_seg == NULL) {
+ return 0;
+ }
+
+ struct dyld_info_command *dyld_info_cmd = this->dyld_info_cmd;
+ struct linkedit_data_command *exports_trie_cmd = this->exports_trie_cmd;
+ if (exports_trie_cmd == NULL && dyld_info_cmd == NULL)
+ return 0;
+
+ uint32_t trieFileOffset = dyld_info_cmd ? dyld_info_cmd->export_off : exports_trie_cmd->dataoff;
+ uint32_t trieFileSize = dyld_info_cmd ? dyld_info_cmd->export_size : exports_trie_cmd->datasize;
+
+ void *exports = (void *)(this->linkedit_base + trieFileOffset);
+ if (exports == NULL)
+ return 0;
+
+ uint8_t *exports_start = (uint8_t *)exports;
+ uint8_t *exports_end = exports_start + trieFileSize;
+ uint8_t *node = (uint8_t *)tail_walk(exports_start, exports_end, symbol_name);
+ if (node == NULL)
+ return 0;
+ const uint8_t *p = node;
+ const uintptr_t flags = read_uleb128(&p, exports_end);
+ if (out_flags)
+ *out_flags = flags;
+ if (flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
+ const uint64_t ordinal = read_uleb128(&p, exports_end);
+ const char *importedName = (const char *)p;
+ if (importedName[0] == '\0') {
+ importedName = symbol_name;
+ return 0;
+ }
+ // trick
+ // printf("reexported symbol: %s\n", importedName);
+ return (uintptr_t)importedName;
+ }
+ uint64_t trieValue = read_uleb128(&p, exports_end);
+ return trieValue;
+#if 0
+ if (off == (void *)0) {
+ if (symbol_name[0] != '_' && strlen(&symbol_name[1]) >= 1) {
+ char _symbol_name[1024] = {0};
+ _symbol_name[0] = '_';
+ strcpy(&_symbol_name[1], symbol_name);
+ off = (void *)walk_exported_trie((const uint8_t *)exports, (const uint8_t *)exports + trieFileSize, _symbol_name);
+ }
+ }
+#endif
+}
+
+uintptr_t macho_ctx_t::symbol_resolve_options(const char *symbol_name_pattern, resolve_symbol_type_t type) {
+ if (type & RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE) {
+ uintptr_t result = iterate_symbol_table(symbol_name_pattern);
+ if (result) {
+ result = result + (this->is_runtime_mode ? this->slide : 0);
+ return result;
+ }
+ }
+
+ if (type & RESOLVE_SYMBOL_TYPE_EXPORTED) {
+ // binary exported table(uleb128)
+ uint64_t flags;
+ uintptr_t result = iterate_exported_symbol(symbol_name_pattern, &flags);
+ if (result) {
+ switch (flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) {
+ case EXPORT_SYMBOL_FLAGS_KIND_REGULAR: {
+ result += (uintptr_t)this->header;
+ } break;
+ case EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL: {
+ result += (uintptr_t)this->header;
+ } break;
+ case EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE: {
+ } break;
+ default:
+ break;
+ }
+ return result;
+ }
+ }
+ return 0;
+}
+
+uintptr_t macho_ctx_t::symbol_resolve(const char *symbol_name_pattern) {
+ return symbol_resolve_options(symbol_name_pattern, RESOLVE_SYMBOL_TYPE_ALL);
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.h
new file mode 100644
index 0000000..82f41cd
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_ctx.h
@@ -0,0 +1,86 @@
+#pragma once
+
+#include
+#include
+#include
+
+#if defined(__LP64__)
+typedef struct mach_header_64 mach_header_t;
+typedef struct segment_command_64 segment_command_t;
+typedef struct section_64 section_t;
+typedef struct nlist_64 nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64
+#else
+typedef struct mach_header mach_header_t;
+typedef struct segment_command segment_command_t;
+typedef struct section section_t;
+typedef struct nlist nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT
+#endif
+
+intptr_t read_sleb128(const uint8_t **pp, const uint8_t *end);
+
+uintptr_t read_uleb128(const uint8_t **pp, const uint8_t *end);
+
+typedef enum {
+ RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE = 1 << 0,
+ RESOLVE_SYMBOL_TYPE_EXPORTED = 1 << 1,
+ RESOLVE_SYMBOL_TYPE_ALL = RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE | RESOLVE_SYMBOL_TYPE_EXPORTED
+} resolve_symbol_type_t;
+
+struct macho_ctx_t {
+ bool is_runtime_mode;
+
+ mach_header_t *header;
+
+ uintptr_t vmaddr;
+ size_t vmsize;
+ uintptr_t vm_region_start;
+ uintptr_t vm_region_end;
+
+ uintptr_t slide;
+ uintptr_t linkedit_base;
+
+ segment_command_t *segments[64];
+ int segments_count;
+
+ segment_command_t *text_seg;
+ segment_command_t *data_seg;
+ segment_command_t *text_exec_seg;
+ segment_command_t *data_const_seg;
+ segment_command_t *linkedit_seg;
+
+ struct symtab_command *symtab_cmd;
+ struct dysymtab_command *dysymtab_cmd;
+ struct dyld_info_command *dyld_info_cmd;
+ struct linkedit_data_command *exports_trie_cmd;
+ struct linkedit_data_command *chained_fixups_cmd;
+
+ nlist_t *symtab;
+ char *strtab;
+ uint32_t *indirect_symtab;
+
+ explicit macho_ctx_t(mach_header_t *header, bool is_runtime_mode = true) {
+ init(header, is_runtime_mode);
+ }
+
+ void init(mach_header_t *header, bool is_runtime_mode);
+
+ uintptr_t iterate_symbol_table(const char *symbol_name_pattern);
+
+ uintptr_t iterate_exported_symbol(const char *symbol_name, uint64_t *out_flags);
+
+ uintptr_t symbol_resolve_options(const char *symbol_name_pattern, resolve_symbol_type_t type);
+
+ uintptr_t symbol_resolve(const char *symbol_name_pattern);
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uintptr_t macho_iterate_symbol_table(char *name_pattern, nlist_t *symtab, uint32_t symtab_count, char *strtab);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.cpp b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.cpp
new file mode 100644
index 0000000..541afd2
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.cpp
@@ -0,0 +1,68 @@
+#include "macho_file_symbol_resolver.h"
+
+#include "SymbolResolver/mmap_file_util.h"
+
+#include
+#include
+#include
+
+uintptr_t macho_file_memory_symbol_resolve(cpu_type_t in_cputype, cpu_subtype_t in_cpusubtype, const uint8_t *file_mem,
+ char *symbol_name_pattern) {
+
+ mach_header_t *header = (mach_header_t *)file_mem;
+ struct fat_header *fh = (struct fat_header *)file_mem;
+ if (fh->magic == OSSwapBigToHostInt32(FAT_MAGIC)) {
+ const struct fat_arch *archs = (struct fat_arch *)(((uintptr_t)fh) + sizeof(fat_header));
+ mach_header_t *header_arm64 = NULL;
+ mach_header_t *header_arm64e = NULL;
+ mach_header_t *header_x64 = NULL;
+ for (size_t i = 0; i < OSSwapBigToHostInt32(fh->nfat_arch); i++) {
+ uint64_t offset;
+ uint64_t len;
+ cpu_type_t cputype = (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype);
+ cpu_subtype_t cpusubtype = (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype);
+ offset = OSSwapBigToHostInt32(archs[i].offset);
+ len = OSSwapBigToHostInt32(archs[i].size);
+ if (cputype == CPU_TYPE_X86_64) {
+ header_x64 = (mach_header_t *)&file_mem[offset];
+ } else if (cputype == CPU_TYPE_ARM64 && (cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) {
+ header_arm64e = (mach_header_t *)&file_mem[offset];
+ } else if (cputype == CPU_TYPE_ARM64) {
+ header_arm64 = (mach_header_t *)&file_mem[offset];
+ }
+
+ if ((cputype == in_cputype) && ((cpusubtype & in_cpusubtype) == in_cpusubtype)) {
+ header = (mach_header_t *)&file_mem[offset];
+ break;
+ }
+ }
+
+ if (header == (mach_header_t *)file_mem) {
+ if (in_cputype == 0 && in_cpusubtype == 0) {
+#if defined(__arm64__) || defined(__aarch64__)
+ header = header_arm64e ? header_arm64e : header_arm64;
+#else
+ header = header_x64;
+#endif
+ }
+ }
+ }
+
+ macho_ctx_t ctx(header, false);
+ return ctx.symbol_resolve_options(symbol_name_pattern, RESOLVE_SYMBOL_TYPE_SYMBOL_TABLE);
+}
+
+uintptr_t macho_file_symbol_resolve(cpu_type_t cpu, cpu_subtype_t subtype, const char *file,
+ char *symbol_name_pattern) {
+
+#if defined(COMPILE_WITH_NO_STDLIB)
+ return 0;
+#endif
+ MmapFileManager mng(file);
+ auto mmap_buffer = mng.map();
+ if (!mmap_buffer) {
+ return 0;
+ }
+
+ return macho_file_memory_symbol_resolve(cpu, subtype, mmap_buffer, symbol_name_pattern);
+}
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.h
new file mode 100644
index 0000000..81700c9
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/macho_file_symbol_resolver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "macho_ctx.h"
+
+uintptr_t macho_file_memory_symbol_resolve(cpu_type_t cpu, cpu_subtype_t subtype, const uint8_t *file_mem,
+ char *symbol_name_pattern);
+
+uintptr_t macho_file_symbol_resolve(cpu_type_t cpu, cpu_subtype_t subtype, const char *file, char *symbol_name_pattern);
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared-cache/dyld_cache_format.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared-cache/dyld_cache_format.h
new file mode 100644
index 0000000..9209293
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared-cache/dyld_cache_format.h
@@ -0,0 +1,560 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2006-2015 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef __DYLD_CACHE_FORMAT__
+#define __DYLD_CACHE_FORMAT__
+
+#include
+#include
+#include
+
+
+struct dyld_cache_header
+{
+ char magic[16]; // e.g. "dyld_v0 i386"
+ uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info
+ uint32_t mappingCount; // number of dyld_cache_mapping_info entries
+ uint32_t imagesOffsetOld; // UNUSED: moved to imagesOffset to prevent older dsc_extarctors from crashing
+ uint32_t imagesCountOld; // UNUSED: moved to imagesCount to prevent older dsc_extarctors from crashing
+ uint64_t dyldBaseAddress; // base address of dyld when cache was built
+ uint64_t codeSignatureOffset; // file offset of code signature blob
+ uint64_t codeSignatureSize; // size of code signature blob (zero means to end of file)
+ uint64_t slideInfoOffsetUnused; // unused. Used to be file offset of kernel slid info
+ uint64_t slideInfoSizeUnused; // unused. Used to be size of kernel slid info
+ uint64_t localSymbolsOffset; // file offset of where local symbols are stored
+ uint64_t localSymbolsSize; // size of local symbols information
+ uint8_t uuid[16]; // unique value for each shared cache file
+ uint64_t cacheType; // 0 for development, 1 for production, 2 for multi-cache
+ uint32_t branchPoolsOffset; // file offset to table of uint64_t pool addresses
+ uint32_t branchPoolsCount; // number of uint64_t entries
+ uint64_t dyldInCacheMH; // (unslid) address of mach_header of dyld in cache
+ uint64_t dyldInCacheEntry; // (unslid) address of entry point (_dyld_start) of dyld in cache
+ uint64_t imagesTextOffset; // file offset to first dyld_cache_image_text_info
+ uint64_t imagesTextCount; // number of dyld_cache_image_text_info entries
+ uint64_t patchInfoAddr; // (unslid) address of dyld_cache_patch_info
+ uint64_t patchInfoSize; // Size of all of the patch information pointed to via the dyld_cache_patch_info
+ uint64_t otherImageGroupAddrUnused; // unused
+ uint64_t otherImageGroupSizeUnused; // unused
+ uint64_t progClosuresAddr; // (unslid) address of list of program launch closures
+ uint64_t progClosuresSize; // size of list of program launch closures
+ uint64_t progClosuresTrieAddr; // (unslid) address of trie of indexes into program launch closures
+ uint64_t progClosuresTrieSize; // size of trie of indexes into program launch closures
+ uint32_t platform; // platform number (macOS=1, etc)
+ uint32_t formatVersion : 8, // dyld3::closure::kFormatVersion
+ dylibsExpectedOnDisk : 1, // dyld should expect the dylib exists on disk and to compare inode/mtime to see if cache is valid
+ simulator : 1, // for simulator of specified platform
+ locallyBuiltCache : 1, // 0 for B&I built cache, 1 for locally built cache
+ builtFromChainedFixups : 1, // some dylib in cache was built using chained fixups, so patch tables must be used for overrides
+ padding : 20; // TBD
+ uint64_t sharedRegionStart; // base load address of cache if not slid
+ uint64_t sharedRegionSize; // overall size required to map the cache and all subCaches, if any
+ uint64_t maxSlide; // runtime slide of cache can be between zero and this value
+ uint64_t dylibsImageArrayAddr; // (unslid) address of ImageArray for dylibs in this cache
+ uint64_t dylibsImageArraySize; // size of ImageArray for dylibs in this cache
+ uint64_t dylibsTrieAddr; // (unslid) address of trie of indexes of all cached dylibs
+ uint64_t dylibsTrieSize; // size of trie of cached dylib paths
+ uint64_t otherImageArrayAddr; // (unslid) address of ImageArray for dylibs and bundles with dlopen closures
+ uint64_t otherImageArraySize; // size of ImageArray for dylibs and bundles with dlopen closures
+ uint64_t otherTrieAddr; // (unslid) address of trie of indexes of all dylibs and bundles with dlopen closures
+ uint64_t otherTrieSize; // size of trie of dylibs and bundles with dlopen closures
+ uint32_t mappingWithSlideOffset; // file offset to first dyld_cache_mapping_and_slide_info
+ uint32_t mappingWithSlideCount; // number of dyld_cache_mapping_and_slide_info entries
+ uint64_t dylibsPBLStateArrayAddrUnused; // unused
+ uint64_t dylibsPBLSetAddr; // (unslid) address of PrebuiltLoaderSet of all cached dylibs
+ uint64_t programsPBLSetPoolAddr; // (unslid) address of pool of PrebuiltLoaderSet for each program
+ uint64_t programsPBLSetPoolSize; // size of pool of PrebuiltLoaderSet for each program
+ uint64_t programTrieAddr; // (unslid) address of trie mapping program path to PrebuiltLoaderSet
+ uint32_t programTrieSize;
+ uint32_t osVersion; // OS Version of dylibs in this cache for the main platform
+ uint32_t altPlatform; // e.g. iOSMac on macOS
+ uint32_t altOsVersion; // e.g. 14.0 for iOSMac
+ uint64_t swiftOptsOffset; // VM offset from cache_header* to Swift optimizations header
+ uint64_t swiftOptsSize; // size of Swift optimizations header
+ uint32_t subCacheArrayOffset; // file offset to first dyld_subcache_entry
+ uint32_t subCacheArrayCount; // number of subCache entries
+ uint8_t symbolFileUUID[16]; // unique value for the shared cache file containing unmapped local symbols
+ uint64_t rosettaReadOnlyAddr; // (unslid) address of the start of where Rosetta can add read-only/executable data
+ uint64_t rosettaReadOnlySize; // maximum size of the Rosetta read-only/executable region
+ uint64_t rosettaReadWriteAddr; // (unslid) address of the start of where Rosetta can add read-write data
+ uint64_t rosettaReadWriteSize; // maximum size of the Rosetta read-write region
+ uint32_t imagesOffset; // file offset to first dyld_cache_image_info
+ uint32_t imagesCount; // number of dyld_cache_image_info entries
+ uint32_t cacheSubType; // 0 for development, 1 for production, when cacheType is multi-cache(2)
+ uint64_t objcOptsOffset; // VM offset from cache_header* to ObjC optimizations header
+ uint64_t objcOptsSize; // size of ObjC optimizations header
+ uint64_t cacheAtlasOffset; // VM offset from cache_header* to embedded cache atlas for process introspection
+ uint64_t cacheAtlasSize; // size of embedded cache atlas
+ uint64_t dynamicDataOffset; // VM offset from cache_header* to the location of dyld_cache_dynamic_data_header
+ uint64_t dynamicDataMaxSize; // maximum size of space reserved from dynamic data
+};
+
+// Uncomment this and check the build errors for the current mapping offset to check against when adding new fields.
+// template class A { int x[-size]; }; A a;
+
+
+struct dyld_cache_mapping_info {
+ uint64_t address;
+ uint64_t size;
+ uint64_t fileOffset;
+ uint32_t maxProt;
+ uint32_t initProt;
+};
+
+// Contains the flags for the dyld_cache_mapping_and_slide_info flgs field
+enum {
+ DYLD_CACHE_MAPPING_AUTH_DATA = 1 << 0U,
+ DYLD_CACHE_MAPPING_DIRTY_DATA = 1 << 1U,
+ DYLD_CACHE_MAPPING_CONST_DATA = 1 << 2U,
+ DYLD_CACHE_MAPPING_TEXT_STUBS = 1 << 3U,
+ DYLD_CACHE_DYNAMIC_CONFIG_DATA = 1 << 4U,
+};
+
+struct dyld_cache_mapping_and_slide_info {
+ uint64_t address;
+ uint64_t size;
+ uint64_t fileOffset;
+ uint64_t slideInfoFileOffset;
+ uint64_t slideInfoFileSize;
+ uint64_t flags;
+ uint32_t maxProt;
+ uint32_t initProt;
+};
+
+struct dyld_cache_image_info
+{
+ uint64_t address;
+ uint64_t modTime;
+ uint64_t inode;
+ uint32_t pathFileOffset;
+ uint32_t pad;
+};
+
+struct dyld_cache_image_info_extra
+{
+ uint64_t exportsTrieAddr; // address of trie in unslid cache
+ uint64_t weakBindingsAddr;
+ uint32_t exportsTrieSize;
+ uint32_t weakBindingsSize;
+ uint32_t dependentsStartArrayIndex;
+ uint32_t reExportsStartArrayIndex;
+};
+
+
+struct dyld_cache_accelerator_info
+{
+ uint32_t version; // currently 1
+ uint32_t imageExtrasCount; // does not include aliases
+ uint32_t imagesExtrasOffset; // offset into this chunk of first dyld_cache_image_info_extra
+ uint32_t bottomUpListOffset; // offset into this chunk to start of 16-bit array of sorted image indexes
+ uint32_t dylibTrieOffset; // offset into this chunk to start of trie containing all dylib paths
+ uint32_t dylibTrieSize; // size of trie containing all dylib paths
+ uint32_t initializersOffset; // offset into this chunk to start of initializers list
+ uint32_t initializersCount; // size of initializers list
+ uint32_t dofSectionsOffset; // offset into this chunk to start of DOF sections list
+ uint32_t dofSectionsCount; // size of initializers list
+ uint32_t reExportListOffset; // offset into this chunk to start of 16-bit array of re-exports
+ uint32_t reExportCount; // size of re-exports
+ uint32_t depListOffset; // offset into this chunk to start of 16-bit array of dependencies (0x8000 bit set if upward)
+ uint32_t depListCount; // size of dependencies
+ uint32_t rangeTableOffset; // offset into this chunk to start of ss
+ uint32_t rangeTableCount; // size of dependencies
+ uint64_t dyldSectionAddr; // address of libdyld's __dyld section in unslid cache
+};
+
+struct dyld_cache_accelerator_initializer
+{
+ uint32_t functionOffset; // address offset from start of cache mapping
+ uint32_t imageIndex;
+};
+
+struct dyld_cache_range_entry
+{
+ uint64_t startAddress; // unslid address of start of region
+ uint32_t size;
+ uint32_t imageIndex;
+};
+
+struct dyld_cache_accelerator_dof
+{
+ uint64_t sectionAddress; // unslid address of start of region
+ uint32_t sectionSize;
+ uint32_t imageIndex;
+};
+
+struct dyld_cache_image_text_info
+{
+ uuid_t uuid;
+ uint64_t loadAddress; // unslid address of start of __TEXT
+ uint32_t textSegmentSize;
+ uint32_t pathOffset; // offset from start of cache file
+};
+
+
+// The rebasing info is to allow the kernel to lazily rebase DATA pages of the
+// dyld shared cache. Rebasing is adding the slide to interior pointers.
+struct dyld_cache_slide_info
+{
+ uint32_t version; // currently 1
+ uint32_t toc_offset;
+ uint32_t toc_count;
+ uint32_t entries_offset;
+ uint32_t entries_count;
+ uint32_t entries_size; // currently 128
+ // uint16_t toc[toc_count];
+ // entrybitmap entries[entries_count];
+};
+
+struct dyld_cache_slide_info_entry {
+ uint8_t bits[4096/(8*4)]; // 128-byte bitmap
+};
+
+
+// The version 2 of the slide info uses a different compression scheme. Since
+// only interior pointers (pointers that point within the cache) are rebased
+// (slid), we know the possible range of the pointers and thus know there are
+// unused bits in each pointer. We use those bits to form a linked list of
+// locations needing rebasing in each page.
+//
+// Definitions:
+//
+// pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size
+// pageStarts[] = info + info->page_starts_offset
+// pageExtras[] = info + info->page_extras_offset
+// valueMask = ~(info->delta_mask)
+// deltaShift = __builtin_ctzll(info->delta_mask) - 2
+//
+// There are three cases:
+//
+// 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE
+// The page contains no values that need rebasing.
+//
+// 2) (pageStarts[pageIndex] & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA) == 0
+// All rebase locations are in one linked list. The offset of the first
+// rebase location in the page is pageStarts[pageIndex] * 4.
+//
+// 3) pageStarts[pageIndex] & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA
+// Multiple linked lists are needed for all rebase locations in a page.
+// The pagesExtras array contains 2 or more entries each of which is the
+// start of a new linked list in the page. The first is at:
+// extrasStartIndex = (pageStarts[pageIndex] & 0x3FFF)
+// The next is at extrasStartIndex+1. The last is denoted by
+// having the high bit (DYLD_CACHE_SLIDE_PAGE_ATTR_END) of the pageExtras[]
+// set.
+//
+// For 64-bit architectures, there is always enough free bits to encode all
+// possible deltas. The info->delta_mask field shows where the delta is located
+// in the pointer. That value must be masked off (valueMask) before the slide
+// is added to the pointer.
+//
+// For 32-bit architectures, there are only three bits free (the three most
+// significant bits). To extract the delta, you must first subtract value_add
+// from the pointer value, then AND with delta_mask, then shift by deltaShift.
+// That still leaves a maximum delta to the next rebase location of 28 bytes.
+// To reduce the number or chains needed, an optimization was added. Turns
+// out zero is common in the DATA region. A zero can be turned into a
+// non-rebasing entry in the linked list. The can be done because nothing
+// in the shared cache should point out of its dylib to the start of the shared
+// cache.
+//
+// The code for processing a linked list (chain) is:
+//
+// uint32_t delta = 1;
+// while ( delta != 0 ) {
+// uint8_t* loc = pageStart + pageOffset;
+// uintptr_t rawValue = *((uintptr_t*)loc);
+// delta = ((rawValue & deltaMask) >> deltaShift);
+// uintptr_t newValue = (rawValue & valueMask);
+// if ( newValue != 0 ) {
+// newValue += valueAdd;
+// newValue += slideAmount;
+// }
+// *((uintptr_t*)loc) = newValue;
+// pageOffset += delta;
+// }
+//
+//
+struct dyld_cache_slide_info2
+{
+ uint32_t version; // currently 2
+ uint32_t page_size; // currently 4096 (may also be 16384)
+ uint32_t page_starts_offset;
+ uint32_t page_starts_count;
+ uint32_t page_extras_offset;
+ uint32_t page_extras_count;
+ uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location
+ uint64_t value_add;
+ //uint16_t page_starts[page_starts_count];
+ //uint16_t page_extras[page_extras_count];
+};
+#define DYLD_CACHE_SLIDE_PAGE_ATTRS 0xC000 // high bits of uint16_t are flags
+#define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA 0x8000 // index is into extras array (not starts array)
+#define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE 0x4000 // page has no rebasing
+#define DYLD_CACHE_SLIDE_PAGE_ATTR_END 0x8000 // last chain entry for page
+
+
+
+// The version 3 of the slide info uses a different compression scheme. Since
+// only interior pointers (pointers that point within the cache) are rebased
+// (slid), we know the possible range of the pointers and thus know there are
+// unused bits in each pointer. We use those bits to form a linked list of
+// locations needing rebasing in each page.
+//
+// Definitions:
+//
+// pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size
+// pageStarts[] = info + info->page_starts_offset
+//
+// There are two cases:
+//
+// 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE
+// The page contains no values that need rebasing.
+//
+// 2) otherwise...
+// All rebase locations are in one linked list. The offset of the first
+// rebase location in the page is pageStarts[pageIndex].
+//
+// A pointer is one of of the variants in dyld_cache_slide_pointer3
+//
+// The code for processing a linked list (chain) is:
+//
+// uint32_t delta = pageStarts[pageIndex];
+// dyld_cache_slide_pointer3* loc = pageStart;
+// do {
+// loc += delta;
+// delta = loc->offsetToNextPointer;
+// if ( loc->auth.authenticated ) {
+// newValue = loc->offsetFromSharedCacheBase + results->slide + auth_value_add;
+// newValue = sign_using_the_various_bits(newValue);
+// }
+// else {
+// uint64_t value51 = loc->pointerValue;
+// uint64_t top8Bits = value51 & 0x0007F80000000000ULL;
+// uint64_t bottom43Bits = value51 & 0x000007FFFFFFFFFFULL;
+// uint64_t targetValue = ( top8Bits << 13 ) | bottom43Bits;
+// newValue = targetValue + results->slide;
+// }
+// loc->raw = newValue;
+// } while (delta != 0);
+//
+//
+struct dyld_cache_slide_info3
+{
+ uint32_t version; // currently 3
+ uint32_t page_size; // currently 4096 (may also be 16384)
+ uint32_t page_starts_count;
+ uint64_t auth_value_add;
+ uint16_t page_starts[/* page_starts_count */];
+};
+
+#define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF // page has no rebasing
+
+union dyld_cache_slide_pointer3
+{
+ uint64_t raw;
+ struct {
+ uint64_t pointerValue : 51,
+ offsetToNextPointer : 11,
+ unused : 2;
+ } plain;
+
+ struct {
+ uint64_t offsetFromSharedCacheBase : 32,
+ diversityData : 16,
+ hasAddressDiversity : 1,
+ key : 2,
+ offsetToNextPointer : 11,
+ unused : 1,
+ authenticated : 1; // = 1;
+ } auth;
+};
+
+
+
+// The version 4 of the slide info is optimized for 32-bit caches up to 1GB.
+// Since only interior pointers (pointers that point within the cache) are rebased
+// (slid), we know the possible range of the pointers takes 30 bits. That
+// gives us two bits to use to chain to the next rebase.
+//
+// Definitions:
+//
+// pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size
+// pageStarts[] = info + info->page_starts_offset
+// pageExtras[] = info + info->page_extras_offset
+// valueMask = ~(info->delta_mask)
+// deltaShift = __builtin_ctzll(info->delta_mask) - 2
+//
+// There are three cases:
+//
+// 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE4_PAGE_NO_REBASE
+// The page contains no values that need rebasing.
+//
+// 2) (pageStarts[pageIndex] & DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA) == 0
+// All rebase locations are in one linked list. The offset of the first
+// rebase location in the page is pageStarts[pageIndex] * 4.
+//
+// 3) pageStarts[pageIndex] & DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA
+// Multiple chains are needed for all rebase locations in a page.
+// The pagesExtras array contains 2 or more entries each of which is the
+// start of a new chain in the page. The first is at:
+// extrasStartIndex = (pageStarts[pageIndex] & DYLD_CACHE_SLIDE4_PAGE_INDEX)
+// The next is at extrasStartIndex+1. The last is denoted by
+// having the high bit (DYLD_CACHE_SLIDE4_PAGE_EXTRA_END) of the pageExtras[].
+//
+// For 32-bit architectures, there are only two bits free (the two most
+// significant bits). To extract the delta, you must first subtract value_add
+// from the pointer value, then AND with delta_mask, then shift by deltaShift.
+// That still leaves a maximum delta to the next rebase location of 12 bytes.
+// To reduce the number or chains needed, an optimization was added. Turns
+// most of the non-rebased data are small values and can be co-opt'ed into
+// being used in the chain. The can be done because nothing
+// in the shared cache should point to the first 64KB which are in the shared
+// cache header information. So if the resulting pointer points to the
+// start of the cache +/-32KB, then it is actually a small number that should
+// not be rebased, but just reconstituted.
+//
+// The code for processing a linked list (chain) is:
+//
+// uint32_t delta = 1;
+// while ( delta != 0 ) {
+// uint8_t* loc = pageStart + pageOffset;
+// uint32_t rawValue = *((uint32_t*)loc);
+// delta = ((rawValue & deltaMask) >> deltaShift);
+// uintptr_t newValue = (rawValue & valueMask);
+// if ( (newValue & 0xFFFF8000) == 0 ) {
+// // small positive non-pointer, use as-is
+// }
+// else if ( (newValue & 0x3FFF8000) == 0x3FFF8000 ) {
+// // small negative non-pointer
+// newValue |= 0xC0000000;
+// }
+// else {
+// // pointer that needs rebasing
+// newValue += valueAdd;
+// newValue += slideAmount;
+// }
+// *((uint32_t*)loc) = newValue;
+// pageOffset += delta;
+// }
+//
+//
+struct dyld_cache_slide_info4
+{
+ uint32_t version; // currently 4
+ uint32_t page_size; // currently 4096 (may also be 16384)
+ uint32_t page_starts_offset;
+ uint32_t page_starts_count;
+ uint32_t page_extras_offset;
+ uint32_t page_extras_count;
+ uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location (0xC0000000)
+ uint64_t value_add; // base address of cache
+ //uint16_t page_starts[page_starts_count];
+ //uint16_t page_extras[page_extras_count];
+};
+#define DYLD_CACHE_SLIDE4_PAGE_NO_REBASE 0xFFFF // page has no rebasing
+#define DYLD_CACHE_SLIDE4_PAGE_INDEX 0x7FFF // mask of page_starts[] values
+#define DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA 0x8000 // index is into extras array (not a chain start offset)
+#define DYLD_CACHE_SLIDE4_PAGE_EXTRA_END 0x8000 // last chain entry for page
+
+
+struct dyld_cache_local_symbols_info
+{
+ uint32_t nlistOffset; // offset into this chunk of nlist entries
+ uint32_t nlistCount; // count of nlist entries
+ uint32_t stringsOffset; // offset into this chunk of string pool
+ uint32_t stringsSize; // byte count of string pool
+ uint32_t entriesOffset; // offset into this chunk of array of dyld_cache_local_symbols_entry
+ uint32_t entriesCount; // number of elements in dyld_cache_local_symbols_entry array
+};
+
+struct dyld_cache_local_symbols_entry
+{
+ uint32_t dylibOffset; // offset in cache file of start of dylib
+ uint32_t nlistStartIndex; // start index of locals for this dylib
+ uint32_t nlistCount; // number of local symbols for this dylib
+};
+
+struct dyld_cache_local_symbols_entry_64
+{
+ uint64_t dylibOffset; // offset in cache buffer of start of dylib
+ uint32_t nlistStartIndex; // start index of locals for this dylib
+ uint32_t nlistCount; // number of local symbols for this dylib
+};
+
+struct dyld_subcache_entry_v1
+{
+ uint8_t uuid[16]; // The UUID of the subCache file
+ uint64_t cacheVMOffset; // The offset of this subcache from the main cache base address
+};
+
+struct dyld_subcache_entry
+{
+ uint8_t uuid[16]; // The UUID of the subCache file
+ uint64_t cacheVMOffset; // The offset of this subcache from the main cache base address
+ char fileSuffix[32]; // The file name suffix of the subCache file e.g. ".25.data", ".03.development"
+};
+
+// This struct is a small piece of dynamic data that can be included in the shared region, and contains configuration
+// data about the shared cache in use by the process. It is located
+struct dyld_cache_dynamic_data_header
+{
+ char magic[16]; // e.g. "dyld_data v0"
+ uint64_t fsId; // The fsid_t of the shared cache being used by a process
+ uint64_t fsObjId; // The fs_obj_id_t of the shared cache being used by a process
+};
+
+// This is the location of the macOS shared cache on macOS 11.0 and later
+#define MACOSX_MRM_DYLD_SHARED_CACHE_DIR "/System/Library/dyld/"
+
+// This is old define for the old location of the dyld cache
+#define MACOSX_DYLD_SHARED_CACHE_DIR MACOSX_MRM_DYLD_SHARED_CACHE_DIR
+
+#define IPHONE_DYLD_SHARED_CACHE_DIR "/System/Library/Caches/com.apple.dyld/"
+
+#define DRIVERKIT_DYLD_SHARED_CACHE_DIR "/System/DriverKit/System/Library/dyld/"
+
+#if !TARGET_OS_SIMULATOR
+ #define DYLD_SHARED_CACHE_BASE_NAME "dyld_shared_cache_"
+#else
+ #define DYLD_SHARED_CACHE_BASE_NAME "dyld_sim_shared_cache_"
+#endif
+#define DYLD_SHARED_CACHE_DEVELOPMENT_EXT ".development"
+
+#define DYLD_SHARED_CACHE_DYNAMIC_DATA_MAGIC "dyld_data v0"
+
+static const char* cryptexPrefixes[] = {
+ "/System/Volumes/Preboot/Cryptexes/OS/",
+ "/private/preboot/Cryptexes/OS/",
+ "/System/Cryptexes/OS"
+};
+
+static const uint64_t kDyldSharedCacheTypeDevelopment = 0;
+static const uint64_t kDyldSharedCacheTypeProduction = 1;
+static const uint64_t kDyldSharedCacheTypeUniversal = 2;
+
+
+
+
+
+#endif // __DYLD_CACHE_FORMAT__
+
+
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.cpp b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.cpp
new file mode 100644
index 0000000..2c9db23
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.cpp
@@ -0,0 +1,183 @@
+#include "shared_cache_ctx.h"
+
+#include
+#include
+#include
+
+#include "logging/logging.h"
+
+#include "mmap_file_util.h"
+
+typedef uintptr_t addr_t;
+
+extern "C" {
+extern const char *dyld_shared_cache_file_path();
+extern int __shared_region_check_np(uint64_t *startaddress);
+}
+
+const char *shared_cache_get_file_path() {
+ return dyld_shared_cache_file_path();
+}
+
+struct dyld_cache_header *shared_cache_get_load_addr() {
+ addr_t shared_cache_base = 0;
+ if (__shared_region_check_np((uint64_t *)&shared_cache_base) != 0) {
+ WARN_LOG("__shared_region_check_np failed");
+ }
+
+ if (shared_cache_base)
+ return (struct dyld_cache_header *)shared_cache_base;
+
+ // task info
+ task_dyld_info_data_t task_dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ kern_return_t ret = task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count);
+ if (ret != KERN_SUCCESS) {
+ ERROR_LOG("task_info failed, ret: %d", ret);
+ return NULL;
+ }
+
+ // get dyld load address
+ auto *infos = (struct dyld_all_image_infos *)(uintptr_t)task_dyld_info.all_image_info_addr;
+ auto *shared_cache = (struct dyld_cache_header *)infos->sharedCacheBaseAddress;
+ return shared_cache;
+}
+
+int shared_cache_load_symbols(shared_cache_ctx_t *ctx) {
+ uint64_t localSymbolsOffset = 0;
+
+ bool latest_shared_cache_format = true;
+
+ const char *shared_cache_path = shared_cache_get_file_path();
+ char shared_cache_symbols_path[4096] = {0};
+ {
+ strcat(shared_cache_symbols_path, shared_cache_path);
+ strcat(shared_cache_symbols_path, ".symbols");
+ }
+
+ auto mmapSharedCacheSymbolsMng = new MmapFileManager(shared_cache_symbols_path);
+ auto mmap_buffer = mmapSharedCacheSymbolsMng->map();
+ if (mmap_buffer) { // iphoneos >= 15.0, which has .symbols file
+ ctx->mmap_shared_cache = (struct dyld_cache_header *)mmap_buffer;
+
+ localSymbolsOffset = ctx->mmap_shared_cache->localSymbolsOffset;
+ } else {
+ // iphoneos < 15.0, which has no .symbols file
+ auto mmapSharedCacheMng = new MmapFileManager(shared_cache_symbols_path);
+
+ auto runtime_shared_cache = ctx->runtime_shared_cache;
+ uint64_t mmap_length = runtime_shared_cache->localSymbolsSize;
+ uint64_t mmap_offset = runtime_shared_cache->localSymbolsOffset;
+
+ if (mmap_length == 0)
+ return -1;
+
+ auto mmap_buffer = mmapSharedCacheMng->map_options(mmap_length, mmap_offset);
+ if (!mmap_buffer) {
+ return -1;
+ }
+
+ // fake shared cache header
+ auto mmap_shared_cache =
+ (struct dyld_cache_header *)((addr_t)mmap_buffer - runtime_shared_cache->localSymbolsOffset);
+ ctx->mmap_shared_cache = mmap_shared_cache;
+
+ localSymbolsOffset = runtime_shared_cache->localSymbolsOffset;
+
+ latest_shared_cache_format = false;
+ }
+ ctx->latest_shared_cache_format = latest_shared_cache_format;
+
+ {
+ auto mmap_shared_cache = ctx->mmap_shared_cache;
+ auto localInfo = (struct dyld_cache_local_symbols_info *)((char *)mmap_shared_cache + localSymbolsOffset);
+ ctx->local_symbols_info = localInfo;
+
+ if (ctx->latest_shared_cache_format) {
+ auto localEntries_64 = (struct dyld_cache_local_symbols_entry_64 *)((char *)localInfo + localInfo->entriesOffset);
+ ctx->local_symbols_entries_64 = localEntries_64;
+ } else {
+ auto localEntries = (struct dyld_cache_local_symbols_entry *)((char *)localInfo + localInfo->entriesOffset);
+ ctx->local_symbols_entries = localEntries;
+ }
+
+ ctx->symtab = (nlist_t *)((char *)localInfo + localInfo->nlistOffset);
+ ctx->strtab = ((char *)localInfo) + localInfo->stringsOffset;
+ }
+
+ return 0;
+}
+
+int shared_cache_ctx_init(shared_cache_ctx_t *ctx) {
+ memset(ctx, 0, sizeof(shared_cache_ctx_t));
+
+ auto runtime_shared_cache = shared_cache_get_load_addr();
+ if (!runtime_shared_cache) {
+ return -1;
+ }
+ ctx->runtime_shared_cache = runtime_shared_cache;
+
+ // shared cache slide
+ auto mappings =
+ (struct dyld_cache_mapping_info *)((char *)runtime_shared_cache + runtime_shared_cache->mappingOffset);
+ uintptr_t slide = (uintptr_t)runtime_shared_cache - (uintptr_t)(mappings[0].address);
+ ctx->runtime_slide = slide;
+
+ return 0;
+}
+
+// refer: dyld
+bool shared_cache_is_contain(shared_cache_ctx_t *ctx, addr_t addr, size_t length) {
+ struct dyld_cache_header *runtime_shared_cache;
+ if (ctx) {
+ runtime_shared_cache = ctx->runtime_shared_cache;
+ } else {
+ runtime_shared_cache = shared_cache_get_load_addr();
+ }
+
+ addr_t region_start = runtime_shared_cache->sharedRegionStart + ctx->runtime_slide;
+ addr_t region_end = region_start + runtime_shared_cache->sharedRegionSize;
+ if (addr >= region_start && addr < region_end)
+ return true;
+
+ return false;
+}
+
+int shared_cache_get_symbol_table(shared_cache_ctx_t *ctx, mach_header_t *image_header, nlist_t **out_symtab,
+ uint32_t *out_symtab_count, char **out_strtab) {
+ uint64_t textOffsetInCache = (uint64_t)image_header - (uint64_t)ctx->runtime_shared_cache;
+
+ nlist_t *localNlists = NULL;
+ uint32_t localNlistCount = 0;
+ const char *localStrings = NULL;
+
+ const uint32_t entriesCount = ctx->local_symbols_info->entriesCount;
+ for (uint32_t i = 0; i < entriesCount; ++i) {
+ if (ctx->latest_shared_cache_format) {
+ if (ctx->local_symbols_entries_64[i].dylibOffset == textOffsetInCache) {
+ uint32_t localNlistStart = ctx->local_symbols_entries_64[i].nlistStartIndex;
+ localNlistCount = ctx->local_symbols_entries_64[i].nlistCount;
+ localNlists = &ctx->symtab[localNlistStart];
+ break;
+ }
+ } else {
+ if (ctx->local_symbols_entries[i].dylibOffset == textOffsetInCache) {
+ uint32_t localNlistStart = ctx->local_symbols_entries[i].nlistStartIndex;
+ localNlistCount = ctx->local_symbols_entries[i].nlistCount;
+ localNlists = &ctx->symtab[localNlistStart];
+ break;
+ }
+ }
+
+#if 0
+ static struct dyld_cache_image_info *imageInfos = NULL;
+ imageInfos = (struct dyld_cache_image_info *)((addr_t)g_mmap_shared_cache + g_mmap_shared_cache->imagesOffset);
+ char *image_name = (char *)g_mmap_shared_cache + imageInfos[i].pathFileOffset;
+ INFO_LOG("dyld image: %s", image_name);
+#endif
+ }
+ *out_symtab = localNlists;
+ *out_symtab_count = (uint32_t)localNlistCount;
+ *out_strtab = (char *)ctx->strtab;
+ return 0;
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.h
new file mode 100644
index 0000000..a17fdc5
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/macho/shared_cache_ctx.h
@@ -0,0 +1,45 @@
+#include
+#include
+#include
+
+#include "shared-cache/dyld_cache_format.h"
+
+#if defined(__LP64__)
+typedef struct mach_header_64 mach_header_t;
+typedef struct segment_command_64 segment_command_t;
+typedef struct section_64 section_t;
+typedef struct nlist_64 nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT_64
+#else
+typedef struct mach_header mach_header_t;
+typedef struct segment_command segment_command_t;
+typedef struct section section_t;
+typedef struct nlist nlist_t;
+#define LC_SEGMENT_ARCH_DEPENDENT LC_SEGMENT
+#endif
+
+typedef uintptr_t addr_t;
+
+typedef struct shared_cache_ctx {
+ struct dyld_cache_header *runtime_shared_cache;
+ struct dyld_cache_header *mmap_shared_cache;
+
+ uintptr_t runtime_slide;
+
+ bool latest_shared_cache_format;
+ struct dyld_cache_local_symbols_info *local_symbols_info;
+ struct dyld_cache_local_symbols_entry *local_symbols_entries;
+ struct dyld_cache_local_symbols_entry_64 *local_symbols_entries_64;
+
+ nlist_t *symtab;
+ char *strtab;
+} shared_cache_ctx_t;
+
+int shared_cache_ctx_init(shared_cache_ctx_t *ctx);
+
+int shared_cache_load_symbols(shared_cache_ctx_t *ctx);
+
+bool shared_cache_is_contain(shared_cache_ctx_t *ctx, addr_t addr, size_t length);
+
+int shared_cache_get_symbol_table(shared_cache_ctx_t *ctx, mach_header_t *image_header, nlist_t **out_symtab,
+ uint32_t *out_symtab_count, char **out_strtab);
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/mmap_file_util.h b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/mmap_file_util.h
new file mode 100644
index 0000000..c5b0506
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/mmap_file_util.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct MmapFileManager {
+ const char *file_;
+ uint8_t *mmap_buffer;
+ size_t mmap_buffer_size;
+
+ explicit MmapFileManager(const char *file) : file_(file), mmap_buffer(nullptr) {
+ }
+
+ ~MmapFileManager() {
+ if (mmap_buffer) {
+ munmap((void *)mmap_buffer, mmap_buffer_size);
+ }
+ }
+
+ uint8_t *map() {
+ size_t file_size = 0;
+ {
+ struct stat s;
+ int rt = stat(file_, &s);
+ if (rt != 0) {
+ // printf("mmap %s failed\n", file_);
+ return NULL;
+ }
+ file_size = s.st_size;
+ }
+
+ return map_options(file_size, 0);
+ }
+
+ uint8_t *map_options(size_t in_map_size, off_t in_map_off) {
+ if (!mmap_buffer) {
+ int fd = open(file_, O_RDONLY, 0);
+ if (fd < 0) {
+ // printf("%s open failed\n", file_);
+ return NULL;
+ }
+
+ // auto align
+ auto mmap_buffer = (uint8_t *)mmap(0, in_map_size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, in_map_off);
+ if (mmap_buffer == MAP_FAILED) {
+ // printf("mmap %s failed\n", file_);
+ return NULL;
+ }
+
+ close(fd);
+
+ this->mmap_buffer = mmap_buffer;
+ this->mmap_buffer_size = in_map_size;
+ }
+ return mmap_buffer;
+ }
+};
diff --git a/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/pe/dobby_symbol_resolver.cc b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/pe/dobby_symbol_resolver.cc
new file mode 100644
index 0000000..e1d0502
--- /dev/null
+++ b/app/src/main/cpp/Dobby/builtin-plugin/SymbolResolver/pe/dobby_symbol_resolver.cc
@@ -0,0 +1,26 @@
+#include "SymbolResolver/dobby_symbol_resolver.h"
+#include "dobby/common.h"
+
+#include
+
+#include
+#include
+
+#include "PlatformUtil/ProcessRuntimeUtility.h"
+
+#include
+
+#undef LOG_TAG
+#define LOG_TAG "DobbySymbolResolver"
+
+PUBLIC void *DobbySymbolResolver(const char *image_name, const char *symbol_name_pattern) {
+ void *result = NULL;
+
+ HMODULE hMod = LoadLibraryExA(image_name, NULL, DONT_RESOLVE_DLL_REFERENCES);
+ result = GetProcAddress(hMod, symbol_name_pattern);
+ if (result)
+ return result;
+
+ //result = resolve_elf_internal_symbol(image_name, symbol_name_pattern);
+ return result;
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/cmake/Macros.cmake b/app/src/main/cpp/Dobby/cmake/Macros.cmake
new file mode 100644
index 0000000..5774bef
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/Macros.cmake
@@ -0,0 +1,3 @@
+macro(SET_OPTION option value)
+ set(${option} ${value} CACHE INTERNAL "" FORCE)
+endmacro()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/cmake/Util.cmake b/app/src/main/cpp/Dobby/cmake/Util.cmake
new file mode 100644
index 0000000..fba658e
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/Util.cmake
@@ -0,0 +1,29 @@
+# Check files list exist
+function(check_files_exist CHECK_FILES)
+ foreach (file ${CHECK_FILES})
+ if (NOT EXISTS "${file}")
+ message(FATAL_ERROR "${file} NOT EXISTS!")
+ endif ()
+ endforeach ()
+endfunction(check_files_exist CHECK_FILES)
+
+# Search suffix files
+function(search_suffix_files suffix INPUT_VARIABLE OUTPUT_VARIABLE)
+ set(ResultFiles)
+ foreach (filePath ${${INPUT_VARIABLE}})
+ # message(STATUS "[*] searching *.${suffix} from ${filePath}")
+ file(GLOB files ${filePath}/*.${suffix})
+ set(ResultFiles ${ResultFiles} ${files})
+ endforeach ()
+ set(${OUTPUT_VARIABLE} ${ResultFiles} PARENT_SCOPE)
+endfunction()
+
+
+function(get_absolute_path_list input_list output_list)
+ set(absolute_list)
+ foreach (file ${${input_list}})
+ get_filename_component(absolute_file ${file} ABSOLUTE)
+ list(APPEND absolute_list ${absolute_file})
+ endforeach ()
+ set(${output_list} ${absolute_list} PARENT_SCOPE)
+endfunction()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/cmake/auto_source_group.cmake b/app/src/main/cpp/Dobby/cmake/auto_source_group.cmake
new file mode 100644
index 0000000..f563836
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/auto_source_group.cmake
@@ -0,0 +1,32 @@
+function (auto_source_group _folder _base _pattern)
+ if (ARGC GREATER 3)
+ set(_exclude ${ARGN})
+ else ()
+ set(_exclude)
+ endif ()
+ file (GLOB _files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ ${_folder}/*)
+ set (folder_files)
+ foreach (_fname ${_files})
+ if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_fname})
+ auto_source_group ("${_fname}" "${_base}" "${_pattern}" "${_exclude}")
+ elseif (_fname MATCHES ${_pattern})
+ if(_exclude)
+ if (NOT _fname MATCHES ${_exclude})
+ set(folder_files ${folder_files} ${_fname})
+ endif ()
+ else ()
+ set(folder_files ${folder_files} ${_fname})
+ endif ()
+ endif ()
+ endforeach ()
+
+ string(REPLACE "./" "" _folder2 ${_folder})
+ string(REPLACE "/" "\\" _folder2 ${_folder2})
+ if (_folder2 STREQUAL ".")
+ source_group(${_base} FILES ${folder_files})
+ else ()
+ source_group(${_base}\\${_folder2} FILES ${folder_files})
+ endif ()
+
+ set(AUTO_FILES_RESULT ${AUTO_FILES_RESULT} ${folder_files} PARENT_SCOPE)
+endfunction ()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/cmake/build_environment_check.cmake b/app/src/main/cpp/Dobby/cmake/build_environment_check.cmake
new file mode 100644
index 0000000..790309b
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/build_environment_check.cmake
@@ -0,0 +1,86 @@
+if(__BUILD_ENVIRONMENT_CHECK)
+ return()
+endif()
+set(__BUILD_ENVIRONMENT_CHECK TRUE)
+
+message(STATUS "")
+message(STATUS "********* build environment check ***********")
+
+
+# The Compiler ID
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
+ set(COMPILER.Clang 1)
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+ set(COMPILER.Gcc 1)
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
+elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+ set(COMPILER.MSVC 1)
+else()
+ message (FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER_ID} not configured")
+endif()
+message(STATUS "\tCompiler: \t ${CMAKE_CXX_COMPILER_ID}")
+
+if(MSVC)
+ string(TOLOWER ${MSVC_CXX_ARCHITECTURE_ID} CMAKE_SYSTEM_PROCESSOR)
+ set(CMAKE_SYSTEM_PROCESSOR ${MSVC_CXX_ARCHITECTURE_ID})
+endif()
+
+
+if(DOBBY_BUILD_SILICON)
+ set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_OSX_ARCHITECTURES})
+endif()
+
+string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR)
+
+# The Processor
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*|x64.*")
+ set(PROCESSOR.X86_64 1)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686.*|i386.*|x86.*|amd64.*|AMD64.*")
+ set(PROCESSOR.X86 1)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm64.*")
+ set(PROCESSOR.AARCH64 1)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)")
+ set(PROCESSOR.AARCH64 1)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm.*|ARM.*)")
+ set(PROCESSOR.ARM 1)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
+ message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}")
+ set(PROCESSOR.PPC64LE 1)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
+ message(STATUS "NOT SUPPORT ${CMAKE_SYSTEM_PROCESSOR}")
+ set(PROCESSOR.PPC64 1)
+else()
+ message (FATAL_ERROR "Processor ${CMAKE_SYSTEM_PROCESSOR} not configured")
+endif()
+message(STATUS "\tProcessor:\t ${CMAKE_SYSTEM_PROCESSOR}")
+
+# The System
+if(CMAKE_SYSTEM_NAME MATCHES "^Android")
+ set(SYSTEM.Android 1)
+elseif(CMAKE_SYSTEM_NAME MATCHES "^Windows")
+ set(SYSTEM.Windows 1)
+elseif(CMAKE_SYSTEM_NAME MATCHES "^Linux")
+ set(SYSTEM.Linux 1)
+elseif(CMAKE_SYSTEM_NAME MATCHES "^iOS")
+ set(SYSTEM.iOS 1)
+ set(SYSTEM.Darwin 1)
+elseif(CMAKE_SYSTEM_NAME MATCHES "^macOS")
+ set(SYSTEM.macOS 1)
+ set(SYSTEM.Darwin 1)
+elseif(CMAKE_SYSTEM_NAME MATCHES "^Darwin")
+ if(PROCESSOR.AARCH64 OR PROCESSOR.ARM)
+ set(CMAKE_SYSTEM_NAME "iOS or Silicon")
+ set(SYSTEM.iOS 1)
+ set(SYSTEM.Silicon 1)
+ elseif(PROCESSOR.X86 OR PROCESSOR.X86_64)
+ set(CMAKE_SYSTEM_NAME "macOS")
+ set(SYSTEM.macOS 1)
+ endif()
+ set(SYSTEM.Darwin 1)
+else()
+ message (FATAL_ERROR "System ${CMAKE_SYSTEM_NAME} not configured")
+endif()
+message(STATUS "\tSystem: \t ${CMAKE_SYSTEM_NAME}")
+
+message(STATUS "***************************************")
+message(STATUS "")
diff --git a/app/src/main/cpp/Dobby/cmake/compiler_and_linker.cmake b/app/src/main/cpp/Dobby/cmake/compiler_and_linker.cmake
new file mode 100644
index 0000000..dd60f3e
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/compiler_and_linker.cmake
@@ -0,0 +1,55 @@
+# :< You Shall Not Pass!
+if (0)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Werror")
+endif ()
+
+set(linker_flags "")
+if (NOT DOBBY_DEBUG)
+ set(linker_flags "${linker_flags} -Wl,-x -Wl,-S")
+endif ()
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-stack-protector")
+
+if (SYSTEM.Darwin)
+ # set(compiler_flags "${compiler_flags} -nostdinc++")
+elseif (SYSTEM.Android)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fomit-frame-pointer")
+ if (NOT DOBBY_DEBUG)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
+ set(linker_flags "${linker_flags} -Wl,--gc-sections -Wl,--exclude-libs,ALL")
+ endif ()
+elseif (SYSTEM.Linux)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+ if (COMPILER.Clang)
+ if (PROCESSOR.ARM)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=armv7-unknown-linux-gnueabihf")
+ elseif (PROCESSOR.ARM64)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=aarch64-unknown-linux-gnu")
+ elseif (PROCESSOR.X86)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=i686-unknown-linux-gnu")
+ elseif (PROCESSOR.X86_64)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --target=x86_64-unknown-linux-gnu")
+ endif ()
+ endif ()
+elseif (SYSTEM.Windows)
+endif ()
+
+if (NOT DOBBY_DEBUG)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden")
+endif ()
+
+if (PROCESSOR.ARM)
+ set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch armv7 -x assembler-with-cpp")
+elseif (PROCESSOR.AARCH64)
+ set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch arm64 -x assembler-with-cpp")
+endif ()
+
+# sync cxx with c flags
+set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}")
+
+message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
+message(STATUS "CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}")
+message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}")
+message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
+message(STATUS "CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}")
diff --git a/app/src/main/cpp/Dobby/cmake/dobby.xcode.source.cmake b/app/src/main/cpp/Dobby/cmake/dobby.xcode.source.cmake
new file mode 100644
index 0000000..64fb0e0
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/dobby.xcode.source.cmake
@@ -0,0 +1,94 @@
+set(dobby.SOURCE_FILE_LIST
+ # cpu
+ source/core/arch/CpuFeature.cc
+ source/core/arch/CpuRegister.cc
+
+ # cpu - x86
+ source/core/arch/x86/cpu-x86.cc
+
+ # assembler
+ source/core/assembler/assembler.cc
+ source/core/assembler/assembler-arm.cc
+ source/core/assembler/assembler-arm64.cc
+ source/core/assembler/assembler-ia32.cc
+ source/core/assembler/assembler-x64.cc
+
+ # codegen
+ source/core/codegen/codegen-arm.cc
+ source/core/codegen/codegen-arm64.cc
+ source/core/codegen/codegen-ia32.cc
+ source/core/codegen/codegen-x64.cc
+
+ # executable memory - code buffer
+ source/MemoryAllocator/CodeBuffer/CodeBufferBase.cc
+ source/MemoryAllocator/CodeBuffer/code-buffer-x86.cc
+
+ # executable memory
+ source/MemoryAllocator/AssemblyCodeBuilder.cc
+ source/MemoryAllocator/MemoryArena.cc
+
+ # instruction relocation
+ source/InstructionRelocation/arm/InstructionRelocationARM.cc
+ source/InstructionRelocation/arm64/InstructionRelocationARM64.cc
+ source/InstructionRelocation/x86/X86InstructionRelocation.cc
+ source/InstructionRelocation/x64/InstructionRelocationX64.cc
+
+ source/InstructionRelocation/x86/x86_insn_decode/x86_insn_decode.c
+
+ # intercept routing
+ source/InterceptRouting/InterceptRouting.cpp
+
+ # intercept routing trampoline
+ source/TrampolineBridge/Trampoline/arm/trampoline-arm.cc
+ source/TrampolineBridge/Trampoline/arm64/trampoline-arm64.cc
+ source/TrampolineBridge/Trampoline/x86/trampoline-x86.cc
+ source/TrampolineBridge/Trampoline/x64/trampoline-x64.cc
+
+ # intercept routing plugin (buildin)
+ source/InterceptRouting/Routing/FunctionInlineReplace/function-inline-replace.cc
+ source/InterceptRouting/Routing/FunctionInlineReplace/FunctionInlineReplaceExport.cc
+
+ # plugin register
+ source/InterceptRouting/RoutingPlugin/RoutingPlugin.cc
+
+ # unified interface
+
+ # platform util
+ source/UserMode/PlatformUtil/${platform2}/ProcessRuntimeUtility.cc
+
+ # user mode - platform interface
+ source/UserMode/UnifiedInterface/platform-${platform1}.cc
+
+ # user mode - executable memory
+ source/UserMode/ExecMemory/code-patch-tool-${platform1}.cc
+ source/UserMode/ExecMemory/clear-cache-tool-all.c
+
+ # main
+ source/dobby.cpp
+ source/Interceptor.cpp
+ source/InterceptEntry.cpp
+ )
+
+if(FunctionWrapper OR DynamicBinaryInstrument)
+ set(dobby.SOURCE_FILE_LIST ${dobby.SOURCE_FILE_LIST}
+ # closure trampoline bridge
+ source/TrampolineBridge/ClosureTrampolineBridge/common_bridge_handler.cc
+
+ source/TrampolineBridge/ClosureTrampolineBridge/arm/helper-arm.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm/closure-bridge-arm.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm/ClosureTrampolineARM.cc
+
+ source/TrampolineBridge/ClosureTrampolineBridge/arm64/helper-arm64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure-bridge-arm64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/arm64/ClosureTrampolineARM64.cc
+
+ source/TrampolineBridge/ClosureTrampolineBridge/x64/helper-x64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/x64/closure-bridge-x64.cc
+ source/TrampolineBridge/ClosureTrampolineBridge/x64/ClosureTrampolineX64.cc
+
+ # user mode - multi thread support
+ source/UserMode/MultiThreadSupport/ThreadSupport.cpp
+ source/UserMode/Thread/PlatformThread.cc
+ source/UserMode/Thread/platform-thread-${platform1}.cc
+ )
+endif()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/cmake/platform/platform-darwin.cmake b/app/src/main/cpp/Dobby/cmake/platform/platform-darwin.cmake
new file mode 100644
index 0000000..826c418
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/platform/platform-darwin.cmake
@@ -0,0 +1,30 @@
+# set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR TRUE)
+set(CMAKE_INSTALL_NAME_DIR "@rpath")
+set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
+add_library(DobbyX ${DOBBY_LIBRARY_TYPE} ${dobby.HEADER_FILE_LIST} ${dobby.SOURCE_FILE_LIST} ${logging.SOURCE_FILE_LIST} ${misc_helper.SOURCE_FILE_LIST} ${dobby.plugin.SOURCE_FILE_LIST})
+
+set_target_properties(DobbyX
+ PROPERTIES
+ LINK_FLAGS "${linker_flags}"
+ COMPILE_FLAGS "${compiler_flags}"
+ )
+
+# set framework property
+set_target_properties(DobbyX PROPERTIES
+ FRAMEWORK TRUE
+ FRAMEWORK_VERSION A
+ MACOSX_FRAMEWORK_IDENTIFIER "com.dobby.dobby"
+ # MACOSX_FRAMEWORK_INFO_PLIST Info.plist
+ VERSION 1.0.0 # current version
+ SOVERSION 1.0.0 # compatibility version
+ PUBLIC_HEADER include/dobby.h
+ XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Development"
+ )
+
+if ((SYSTEM.Darwin AND BUILDING_PLUGIN) AND (NOT DOBBY_BUILD_KERNEL_MODE))
+add_subdirectory(builtin-plugin/Dyld2HideLibrary)
+add_subdirectory(builtin-plugin/ObjcRuntimeHook)
+if (PROCESSOR.AARCH64)
+ add_subdirectory(builtin-plugin/SupervisorCallMonitor)
+endif ()
+endif()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/cmake/xcode_generator_helper.cmake b/app/src/main/cpp/Dobby/cmake/xcode_generator_helper.cmake
new file mode 100644
index 0000000..243593d
--- /dev/null
+++ b/app/src/main/cpp/Dobby/cmake/xcode_generator_helper.cmake
@@ -0,0 +1,9 @@
+if(CMAKE_GENERATOR STREQUAL Xcode)
+ message(STATUS "[*] Detect Xcode Project")
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/build/Debug)
+ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/build/Release)
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/build/Debug)
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/build/Release)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/build/Debug)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/build/Release)
+endif()
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/docs/compile.md b/app/src/main/cpp/Dobby/docs/compile.md
new file mode 100644
index 0000000..002dba4
--- /dev/null
+++ b/app/src/main/cpp/Dobby/docs/compile.md
@@ -0,0 +1,89 @@
+# Build
+
+## CMake build options
+
+```
+option(DOBBY_GENERATE_SHARED "Build shared library" ON)
+
+option(DOBBY_DEBUG "Enable debug logging" OFF)
+
+option(NearBranch "Enable near branch trampoline" ON)
+
+option(FullFloatingPointRegisterPack "Save and pack all floating-point registers" OFF)
+
+option(Plugin.SymbolResolver "Enable symbol resolver" ON)
+
+option(Plugin.ImportTableReplace "Enable import table replace " OFF)
+
+option(Plugin.Android.BionicLinkerUtil "Enable android bionic linker util" OFF)
+
+option(DOBBY_BUILD_EXAMPLE "Build example" OFF)
+
+option(DOBBY_BUILD_TEST "Build test" OFF)
+```
+
+## Build with `scripts/platform_builder.py`
+
+#### Build for iphoneos
+
+```shell
+python3 scripts/platform_builder.py --platform=iphoneos --arch=all
+```
+
+#### Build for macos
+
+```
+python3 scripts/platform_builder.py --platform=macos --arch=all
+```
+
+#### Build for linux
+
+```
+# prepare and download cmake/llvm
+sh scripts/setup_linux_cross_compile.sh
+python3 scripts/platform_builder.py --platform=linux --arch=all --cmake_dir=$HOME/opt/cmake-3.25.2 --llvm_dir=$HOME/opt/llvm-15.0.6
+```
+
+#### Build for android
+
+```
+# prepare and download cmake/llvm/ndk
+sh scripts/setup_linux_cross_compile.sh
+python3 scripts/platform_builder.py --platform=android --arch=all --cmake_dir=$HOME/opt/cmake-3.25.2 --llvm_dir=$HOME/opt/llvm-15.0.6 --android_ndk_dir=$HOME/opt/ndk-r25b
+```
+
+## Build with CMake
+
+#### Build for host
+
+```shell
+cd Dobby && mkdir cmake-build-host && cd cmake-build-host
+cmake ..
+make -j4
+```
+
+## Build with Android Studio CMake
+
+```
+if(NOT TARGET dobby)
+set(DOBBY_DIR /Users/jmpews/Workspace/Project.wrk/Dobby)
+macro(SET_OPTION option value)
+ set(${option} ${value} CACHE INTERNAL "" FORCE)
+endmacro()
+SET_OPTION(DOBBY_DEBUG OFF)
+SET_OPTION(DOBBY_GENERATE_SHARED OFF)
+add_subdirectory(${DOBBY_DIR} dobby)
+get_property(DOBBY_INCLUDE_DIRECTORIES
+ TARGET dobby
+ PROPERTY INCLUDE_DIRECTORIES)
+include_directories(
+ .
+ ${DOBBY_INCLUDE_DIRECTORIES}
+ $
+)
+endif()
+
+add_library(native-lib SHARED
+ ${DOBBY_DIR}/examples/socket_example.cc
+ native-lib.cpp)
+```
diff --git a/app/src/main/cpp/Dobby/examples/CMakeLists.txt b/app/src/main/cpp/Dobby/examples/CMakeLists.txt
new file mode 100644
index 0000000..b461a1c
--- /dev/null
+++ b/app/src/main/cpp/Dobby/examples/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_executable(socket_example
+ main.cc
+ socket_example.cc
+ )
+
+target_link_libraries(socket_example
+ dobby
+ logging
+ )
+
+
+add_library(socket_example_lib SHARED
+ socket_example.cc
+ )
+
+target_link_libraries(socket_example_lib
+ dobby
+ )
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/examples/main.cc b/app/src/main/cpp/Dobby/examples/main.cc
new file mode 100644
index 0000000..33eeddf
--- /dev/null
+++ b/app/src/main/cpp/Dobby/examples/main.cc
@@ -0,0 +1,14 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+int main(int argc, char const *argv[]) {
+
+ std::cout << "Start..." << std::endl;
+
+ sleep(100);
+ return 0;
+}
\ No newline at end of file
diff --git a/app/src/main/cpp/Dobby/examples/socket_example.cc b/app/src/main/cpp/Dobby/examples/socket_example.cc
new file mode 100644
index 0000000..1377fa3
--- /dev/null
+++ b/app/src/main/cpp/Dobby/examples/socket_example.cc
@@ -0,0 +1,212 @@
+#include "dobby.h"
+
+#include "logging/logging.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include