├── .gitignore ├── Common ├── ASMHooker │ ├── cmake.sh │ └── whale │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── LICENSE │ │ ├── LOGO.png │ │ ├── README.md │ │ ├── README.zh-CN.md │ │ ├── built │ │ ├── Android │ │ │ ├── arm64-v8a │ │ │ │ └── libwhale.so │ │ │ ├── armeabi-v7a │ │ │ │ └── libwhale.so │ │ │ ├── x86 │ │ │ │ └── libwhale.so │ │ │ └── x86_64 │ │ │ │ └── libwhale.so │ │ └── IOS │ │ │ └── libwhale.dylib │ │ ├── java │ │ └── com │ │ │ └── lody │ │ │ └── whale │ │ │ ├── VMHelper.java │ │ │ ├── WhaleRuntime.java │ │ │ └── xposed │ │ │ ├── ClassUtils.java │ │ │ ├── MemberUtils.java │ │ │ ├── XC_MethodHook.java │ │ │ ├── XC_MethodReplacement.java │ │ │ ├── XposedBridge.java │ │ │ ├── XposedHelpers.java │ │ │ └── callbacks │ │ │ └── XCallback.java │ │ ├── toolchain │ │ └── ios.toolchain.cmake │ │ └── whale │ │ ├── CMakeLists.txt │ │ ├── cpplint.py │ │ ├── include │ │ └── whale.h │ │ ├── src │ │ ├── android │ │ │ ├── android_build.h │ │ │ ├── art │ │ │ │ ├── art_hook_param.h │ │ │ │ ├── art_jni_trampoline.cc │ │ │ │ ├── art_jni_trampoline.h │ │ │ │ ├── art_method.cc │ │ │ │ ├── art_method.h │ │ │ │ ├── art_runtime.cc │ │ │ │ ├── art_runtime.h │ │ │ │ ├── art_symbol_resolver.cc │ │ │ │ ├── art_symbol_resolver.h │ │ │ │ ├── java_types.cc │ │ │ │ ├── java_types.h │ │ │ │ ├── modifiers.h │ │ │ │ ├── native_on_load.cc │ │ │ │ ├── native_on_load.h │ │ │ │ ├── scoped_thread_state_change.cc │ │ │ │ ├── scoped_thread_state_change.h │ │ │ │ ├── well_known_classes.cc │ │ │ │ └── well_known_classes.h │ │ │ ├── jni_helper.h │ │ │ └── native_bridge.h │ │ ├── assembler │ │ │ ├── assembler.cc │ │ │ ├── assembler.h │ │ │ ├── label.h │ │ │ ├── managed_register.h │ │ │ ├── memory_region.cc │ │ │ ├── memory_region.h │ │ │ ├── value_object.h │ │ │ ├── vixl │ │ │ │ ├── CMakeLists.txt │ │ │ │ ├── aarch32 │ │ │ │ │ ├── assembler-aarch32.cc │ │ │ │ │ ├── assembler-aarch32.h │ │ │ │ │ ├── constants-aarch32.cc │ │ │ │ │ ├── constants-aarch32.h │ │ │ │ │ ├── disasm-aarch32.cc │ │ │ │ │ ├── disasm-aarch32.h │ │ │ │ │ ├── instructions-aarch32.cc │ │ │ │ │ ├── instructions-aarch32.h │ │ │ │ │ ├── location-aarch32.cc │ │ │ │ │ ├── location-aarch32.h │ │ │ │ │ ├── macro-assembler-aarch32.cc │ │ │ │ │ ├── macro-assembler-aarch32.h │ │ │ │ │ ├── operands-aarch32.cc │ │ │ │ │ └── operands-aarch32.h │ │ │ │ ├── aarch64 │ │ │ │ │ ├── abi-aarch64.h │ │ │ │ │ ├── assembler-aarch64.cc │ │ │ │ │ ├── assembler-aarch64.h │ │ │ │ │ ├── constants-aarch64.h │ │ │ │ │ ├── cpu-aarch64.cc │ │ │ │ │ ├── cpu-aarch64.h │ │ │ │ │ ├── cpu-features-auditor-aarch64.cc │ │ │ │ │ ├── cpu-features-auditor-aarch64.h │ │ │ │ │ ├── decoder-aarch64.cc │ │ │ │ │ ├── decoder-aarch64.h │ │ │ │ │ ├── disasm-aarch64.cc │ │ │ │ │ ├── disasm-aarch64.h │ │ │ │ │ ├── instructions-aarch64.cc │ │ │ │ │ ├── instructions-aarch64.h │ │ │ │ │ ├── instrument-aarch64.cc │ │ │ │ │ ├── instrument-aarch64.h │ │ │ │ │ ├── logic-aarch64.cc │ │ │ │ │ ├── macro-assembler-aarch64.cc │ │ │ │ │ ├── macro-assembler-aarch64.h │ │ │ │ │ ├── operands-aarch64.cc │ │ │ │ │ ├── operands-aarch64.h │ │ │ │ │ ├── pointer-auth-aarch64.cc │ │ │ │ │ ├── simulator-aarch64.cc │ │ │ │ │ ├── simulator-aarch64.h │ │ │ │ │ └── simulator-constants-aarch64.h │ │ │ │ ├── assembler-base-vixl.h │ │ │ │ ├── code-buffer-vixl.cc │ │ │ │ ├── code-buffer-vixl.h │ │ │ │ ├── code-generation-scopes-vixl.h │ │ │ │ ├── compiler-intrinsics-vixl.cc │ │ │ │ ├── compiler-intrinsics-vixl.h │ │ │ │ ├── cpu-features.cc │ │ │ │ ├── cpu-features.h │ │ │ │ ├── globals-vixl.h │ │ │ │ ├── invalset-vixl.h │ │ │ │ ├── macro-assembler-interface.h │ │ │ │ ├── platform-vixl.h │ │ │ │ ├── pool-manager-impl.h │ │ │ │ ├── pool-manager.h │ │ │ │ ├── utils-vixl.cc │ │ │ │ └── utils-vixl.h │ │ │ ├── x86 │ │ │ │ ├── assembler_x86.cc │ │ │ │ ├── assembler_x86.h │ │ │ │ ├── constants_x86.h │ │ │ │ ├── managed_register_x86.cc │ │ │ │ ├── managed_register_x86.h │ │ │ │ └── registers_x86.h │ │ │ └── x86_64 │ │ │ │ ├── assembler_x86_64.cc │ │ │ │ ├── assembler_x86_64.h │ │ │ │ ├── constants_x86_64.h │ │ │ │ ├── managed_register_x86_64.cc │ │ │ │ ├── managed_register_x86_64.h │ │ │ │ └── registers_x86_64.h │ │ ├── base │ │ │ ├── align.h │ │ │ ├── array_ref.h │ │ │ ├── bit_utils.h │ │ │ ├── cxx_helper.h │ │ │ ├── enums.h │ │ │ ├── logging.h │ │ │ ├── macros.h │ │ │ ├── offsets.h │ │ │ ├── primitive_types.h │ │ │ ├── singleton.h │ │ │ └── stringprintf.h │ │ ├── dbi │ │ │ ├── arm │ │ │ │ ├── decoder_arm.cc │ │ │ │ ├── decoder_arm.h │ │ │ │ ├── decoder_thumb.cc │ │ │ │ ├── decoder_thumb.h │ │ │ │ ├── inline_hook_arm.cc │ │ │ │ ├── inline_hook_arm.h │ │ │ │ ├── instruction_rewriter_arm.cc │ │ │ │ ├── instruction_rewriter_arm.h │ │ │ │ └── registers_arm.h │ │ │ ├── arm64 │ │ │ │ ├── decoder_arm64.cc │ │ │ │ ├── decoder_arm64.h │ │ │ │ ├── inline_hook_arm64.cc │ │ │ │ ├── inline_hook_arm64.h │ │ │ │ ├── instruction_rewriter_arm64.cc │ │ │ │ ├── instruction_rewriter_arm64.h │ │ │ │ └── registers_arm64.h │ │ │ ├── backup_code.h │ │ │ ├── darwin │ │ │ │ ├── macho_import_hook.cc │ │ │ │ └── macho_import_hook.h │ │ │ ├── hook_common.cc │ │ │ ├── hook_common.h │ │ │ ├── instruction_rewriter.h │ │ │ ├── instruction_set.cc │ │ │ ├── instruction_set.h │ │ │ ├── x86 │ │ │ │ ├── distorm │ │ │ │ │ ├── config.h │ │ │ │ │ ├── decoder.c │ │ │ │ │ ├── decoder.h │ │ │ │ │ ├── distorm.c │ │ │ │ │ ├── distorm.h │ │ │ │ │ ├── instructions.c │ │ │ │ │ ├── instructions.h │ │ │ │ │ ├── insts.c │ │ │ │ │ ├── insts.h │ │ │ │ │ ├── mnemonics.c │ │ │ │ │ ├── mnemonics.h │ │ │ │ │ ├── operands.c │ │ │ │ │ ├── operands.h │ │ │ │ │ ├── prefix.c │ │ │ │ │ ├── prefix.h │ │ │ │ │ ├── textdefs.c │ │ │ │ │ ├── textdefs.h │ │ │ │ │ ├── wstring.c │ │ │ │ │ ├── wstring.h │ │ │ │ │ └── x86defs.h │ │ │ │ ├── inline_hook_x86.cc │ │ │ │ ├── inline_hook_x86.h │ │ │ │ ├── instruction_rewriter_x86.cc │ │ │ │ ├── instruction_rewriter_x86.h │ │ │ │ ├── intercept_syscall_x86.cc │ │ │ │ └── intercept_syscall_x86.h │ │ │ └── x86_64 │ │ │ │ ├── inline_hook_x86_64.cc │ │ │ │ ├── inline_hook_x86_64.h │ │ │ │ ├── instruction_rewriter_x86_64.cc │ │ │ │ └── instruction_rewriter_x86_64.h │ │ ├── interceptor.cc │ │ ├── interceptor.h │ │ ├── libffi │ │ │ ├── aarch64 │ │ │ │ ├── ffi_arm64.c │ │ │ │ ├── internal.h │ │ │ │ └── sysv_arm64.S │ │ │ ├── arm │ │ │ │ ├── ffi_armv7.c │ │ │ │ ├── internal.h │ │ │ │ └── sysv_armv7.S │ │ │ ├── closures.c │ │ │ ├── debug.c │ │ │ ├── dlmalloc.c │ │ │ ├── ffi.h │ │ │ ├── ffi_cfi.h │ │ │ ├── ffi_common.h │ │ │ ├── ffi_cxx.cc │ │ │ ├── ffi_cxx.h │ │ │ ├── fficonfig.h │ │ │ ├── ffitarget.h │ │ │ ├── java_raw_api.c │ │ │ ├── platform_include │ │ │ │ ├── ffi_arm64.h │ │ │ │ ├── ffi_armv7.h │ │ │ │ ├── ffi_i386.h │ │ │ │ ├── ffi_x86_64.h │ │ │ │ ├── fficonfig_arm64.h │ │ │ │ ├── fficonfig_armv7.h │ │ │ │ ├── fficonfig_i386.h │ │ │ │ ├── fficonfig_x86_64.h │ │ │ │ ├── ffitarget_arm64.h │ │ │ │ ├── ffitarget_armv7.h │ │ │ │ ├── ffitarget_i386.h │ │ │ │ └── ffitarget_x86_64.h │ │ │ ├── prep_cif.c │ │ │ ├── raw_api.c │ │ │ ├── types.c │ │ │ └── x86 │ │ │ │ ├── asmnames.h │ │ │ │ ├── ffi64_x86_64.c │ │ │ │ ├── ffi_i386.c │ │ │ │ ├── ffiw64_x86_64.c │ │ │ │ ├── internal.h │ │ │ │ ├── internal64.h │ │ │ │ ├── sysv_i386.S │ │ │ │ ├── unix64_x86_64.S │ │ │ │ └── win64_x86_64.S │ │ ├── platform │ │ │ ├── linux │ │ │ │ ├── elf_image.cc │ │ │ │ ├── elf_image.h │ │ │ │ ├── process_map.cc │ │ │ │ └── process_map.h │ │ │ ├── memory.cc │ │ │ └── memory.h │ │ ├── simulator │ │ │ ├── code_simulator.cc │ │ │ ├── code_simulator.h │ │ │ ├── code_simulator_arm64.cc │ │ │ ├── code_simulator_arm64.h │ │ │ ├── code_simulator_container.cc │ │ │ └── code_simulator_container.h │ │ └── whale.cc │ │ └── test │ │ ├── test_emulator.cc │ │ └── test_hook.cc ├── ELFPatcher │ ├── .gitignore │ ├── .travis.yml │ ├── BUGS │ ├── COPYING │ ├── Makefile.am │ ├── README │ ├── bootstrap.sh │ ├── configure.ac │ ├── flake.lock │ ├── flake.nix │ ├── jni │ │ ├── Android.mk │ │ └── Application.mk │ ├── patchelf.1 │ ├── patchelf.spec.in │ ├── release.nix │ ├── src │ │ ├── Makefile.am │ │ ├── elf.h │ │ └── patchelf.cc │ ├── tests │ │ ├── Makefile.am │ │ ├── bar.c │ │ ├── big-dynstr.sh │ │ ├── foo.c │ │ ├── main.c │ │ ├── no-rpath-prebuild │ │ │ ├── no-rpath-amd64 │ │ │ ├── no-rpath-armel │ │ │ ├── no-rpath-armhf │ │ │ ├── no-rpath-hurd-i386 │ │ │ ├── no-rpath-i386 │ │ │ ├── no-rpath-ia64 │ │ │ ├── no-rpath-kfreebsd-amd64 │ │ │ ├── no-rpath-kfreebsd-i386 │ │ │ ├── no-rpath-mips │ │ │ ├── no-rpath-mipsel │ │ │ ├── no-rpath-powerpc │ │ │ ├── no-rpath-s390 │ │ │ ├── no-rpath-sh4 │ │ │ └── no-rpath-sparc │ │ ├── no-rpath.c │ │ ├── no-rpath.sh │ │ ├── plain-fail.sh │ │ ├── plain-run.sh │ │ ├── set-interpreter-long.sh │ │ ├── set-interpreter-short.sh │ │ ├── set-rpath-library.sh │ │ ├── set-rpath.sh │ │ ├── shrink-rpath-with-allowed-prefixes.sh │ │ ├── shrink-rpath.sh │ │ ├── simple.c │ │ └── soname.sh │ └── version ├── PLTHooker │ ├── Android.mk │ ├── Makefile │ ├── README.md │ ├── config.mk │ ├── jni │ │ ├── Android.mk │ │ └── Application.mk │ └── src │ │ ├── elf_common.cpp │ │ ├── elf_common.h │ │ ├── elf_hooker.cpp │ │ ├── elf_hooker.h │ │ ├── elf_module.cpp │ │ ├── elf_module.h │ │ └── main.cpp └── iOSUnicorn │ ├── ios_clang │ └── patch.md ├── LICENSE ├── PantaEngine └── README.md ├── README.md ├── UltimateVMP └── README.md ├── UnicornVM-V7 ├── README.md ├── fridobot │ ├── jni │ │ ├── Android.mk │ │ ├── Application.mk │ │ └── hijackmain.cpp │ └── test.py ├── include │ └── UnicornVM.h ├── sample │ ├── apitest.cpp │ ├── apitest.py │ └── jni │ │ ├── Android.mk │ │ └── Application.mk └── solib │ └── libunicornvm.so ├── UnicornVM-V8 ├── README.md ├── fridobot │ └── test.py ├── include │ └── UnicornVM.h ├── sample │ ├── apitest.cpp │ ├── apitest.py │ └── jni │ │ ├── Android.mk │ │ └── Application.mk └── solib │ └── libunicornvm.so └── UnicornVM-iOS ├── README.md ├── dylib └── libunicornvm.dylib ├── include └── UnicornVM.h ├── sample ├── apitest.mm ├── makefile └── unicornvm_apitest └── textobot └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | obj/ 3 | libs/ 4 | *.o 5 | -------------------------------------------------------------------------------- /Common/ASMHooker/cmake.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | cd ./obj 4 | cmake -DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=release -DANDROID_ABI=$NDK_ABI -DANDROID_PLATFORM=android-24 ../whale 5 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | CMakeCache.txt 4 | CMakeFiles 5 | CMakeScripts 6 | Testing 7 | Makefile 8 | cmake_install.cmake 9 | install_manifest.txt 10 | compile_commands.json 11 | CTestTestfile.cmake 12 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | set(CMAKE_CXX_STANDARD 14) 4 | add_subdirectory(whale) 5 | include_directories(whale/include) 6 | include_directories(whale/src) 7 | 8 | #add_executable(test whale/test/test_hook.cc) 9 | #target_link_libraries(test whale) 10 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/LOGO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ASMHooker/whale/LOGO.png -------------------------------------------------------------------------------- /Common/ASMHooker/whale/README.zh-CN.md: -------------------------------------------------------------------------------- 1 | # Whale 2 | ![logo][0] 3 | 4 | ## 概述 5 | Whale是一个跨平台的Hook Framework,同时支持Android、IOS、Linux、MacOS。 6 | Whale 支持**ARM/THUMB、ARM64、X86、X86_64 (AMD64)**,这几乎覆盖了目前所有主流的设备。 7 | 8 | ## 特性 9 | #### Android 10 | * **Xposed-Style** Method Hook 11 | * 运行时修改类之间的继承关系 12 | * 修改对象所属的类 13 | * 绕过`Hidden API Policy` 14 | 15 | #### Darwin/Linux Platforms 16 | * Internal symbol resolver 17 | * Native Hook 18 | 19 | #### IOS的限制 20 | IOS的InlineHook在非越狱设备上只限在debug编译模式下开启, 21 | release编译模式下将无法正常工作。 22 | 23 | 为了解决这个问题,Whale将提供`Binary Static Inline Hook`。 24 | 25 | IOS下的`Binary Static Inline Hook`将在近期开源。 26 | 27 | 28 | ## 你可以用它做什么? 29 | * 开启App的上帝模式 30 | * 监控或篡改软件的行为 31 | * 即时生效的热修复 32 | * SandBox 33 | * 注入到系统代替Xposed 34 | 35 | ## Whale的兼容性 36 | - [x] Android 5.0.0 37 | - [x] Android 5.1.1 38 | - [x] Android 6.0 39 | - [x] Android 6.0.1 40 | - [x] Android 7.1.2 41 | - [x] Android 8.1.0 42 | - [x] Android 9.0.0 43 | - [x] IOS 11.3 44 | - [x] IOS 12.0 45 | - [x] MacOS mojave (10.14) 46 | - (不在清单内表示 `未测试` ) 47 | 48 | ## InlineHook 49 | 对于`pcrel指令`, Whale会将其转换为`pc 无关指令`, 50 | 如果在Hook过程有遇到未转换的指令,请提`issue`。 51 | 52 | ## 关于Jit 53 | Whale内置了 **Jit Engine**, 当你有更高级的Hook需求时可以通过Jit直接在内存中生成可执行的指令。 54 | 不再需要像从前那样通过工具来生成丑陋的hard code。 55 | 56 | ## 编译 57 | 我们已提前编译了Android & IOS的**二进制版本**,您可以在`built目录`找到它们。 58 | 59 | Whale使用了CMake来构建项目,所以你需要在你的系统上安装CMake。 60 | 61 | #### Android 62 | 1. 如果需要使用`Java Hook`, 请把java文件夹的代码复制到你的项目。 63 | 64 | 2. 直接使用二进制,你只需要复制 `built/Android` 下你所需的abi到你的项目的src/main/jniLibs下。 65 | 66 | 3. 如果需要编译源码,请在build.gradle中指定CMakelists.txt: 67 | ``` 68 | externalNativeBuild { 69 | cmake { 70 | path "your/whale/path/CMakeLists.txt" 71 | } 72 | } 73 | ``` 74 | 75 | #### IOS 76 | ``` 77 | cd toolchain 78 | 79 | cmake .. \ 80 | -DCMAKE_TOOLCHAIN_FILE=ios.toolchain.cmake \ 81 | -DIOS_PLATFORM=OS64 \ 82 | -DPLATFORM=IOS \ 83 | -DIOS_ARCH=arm64 \ 84 | -DENABLE_ARC=0 \ 85 | -DENABLE_BITCODE=0 \ 86 | -DENABLE_VISIBILITY=0 \ 87 | -DIOS_DEPLOYMENT_TARGET=9.3 \ 88 | -DSHARED=ON \ 89 | -DCMAKE_BUILD_TYPE=Release 90 | 91 | make -j4 92 | ``` 93 | 94 | #### Ohter platforms 95 | ``` 96 | cmake . 97 | make -j8 98 | ``` 99 | 100 | ## Technogy communication 101 | > **QQ Group: 977793836** 102 | 103 | 104 | 105 | [0]: https://github.com/asLody/whale/blob/master/LOGO.png?raw=true 106 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/built/Android/arm64-v8a/libwhale.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ASMHooker/whale/built/Android/arm64-v8a/libwhale.so -------------------------------------------------------------------------------- /Common/ASMHooker/whale/built/Android/armeabi-v7a/libwhale.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ASMHooker/whale/built/Android/armeabi-v7a/libwhale.so -------------------------------------------------------------------------------- /Common/ASMHooker/whale/built/Android/x86/libwhale.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ASMHooker/whale/built/Android/x86/libwhale.so -------------------------------------------------------------------------------- /Common/ASMHooker/whale/built/Android/x86_64/libwhale.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ASMHooker/whale/built/Android/x86_64/libwhale.so -------------------------------------------------------------------------------- /Common/ASMHooker/whale/built/IOS/libwhale.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ASMHooker/whale/built/IOS/libwhale.dylib -------------------------------------------------------------------------------- /Common/ASMHooker/whale/java/com/lody/whale/WhaleRuntime.java: -------------------------------------------------------------------------------- 1 | package com.lody.whale; 2 | 3 | import android.os.Build; 4 | 5 | import com.lody.whale.xposed.XposedBridge; 6 | 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.lang.reflect.Member; 9 | import java.lang.reflect.Method; 10 | 11 | /** 12 | * @author Lody 13 | *

14 | * NOTICE: Do not move or rename any methods in this class. 15 | */ 16 | public class WhaleRuntime { 17 | 18 | static { 19 | System.loadLibrary("whale"); 20 | } 21 | 22 | private static String getShorty(Member member) { 23 | return VMHelper.getShorty(member); 24 | } 25 | 26 | public static long[] countInstancesOfClasses(Class[] classes, boolean assignable) { 27 | if (Build.VERSION.SDK_INT < 27) { 28 | throw new UnsupportedOperationException("Not support countInstancesOfClasses on your device yet."); 29 | } 30 | try { 31 | Class clazz = Class.forName("dalvik.system.VMDebug"); 32 | Method method = clazz.getDeclaredMethod("countInstancesOfClasses", Class[].class, boolean.class); 33 | return (long[]) method.invoke(null, classes, assignable); 34 | } catch (Throwable e) { 35 | throw new IllegalStateException(e); 36 | } 37 | } 38 | 39 | public static Object[][] getInstancesOfClasses(Class[] classes, boolean assignable) { 40 | if (Build.VERSION.SDK_INT < 28) { 41 | throw new UnsupportedOperationException("Not support getInstancesOfClasses on your device yet."); 42 | } 43 | try { 44 | Class clazz = Class.forName("dalvik.system.VMDebug"); 45 | Method method = clazz.getDeclaredMethod("getInstancesOfClasses", Class[].class, boolean.class); 46 | return (Object[][]) method.invoke(null, classes, assignable); 47 | } catch (Throwable e) { 48 | throw new IllegalStateException(e); 49 | } 50 | } 51 | 52 | public static Object handleHookedMethod(Member member, long slot, Object additionInfo, Object thisObject, Object[] args) throws Throwable { 53 | return XposedBridge.handleHookedMethod(member, slot, additionInfo, thisObject, args); 54 | } 55 | 56 | public static native Object invokeOriginalMethodNative(long slot, Object thisObject, Object[] args) 57 | throws IllegalAccessException, IllegalArgumentException, InvocationTargetException; 58 | 59 | public static native long getMethodSlot(Member member) throws IllegalArgumentException; 60 | 61 | public static native long hookMethodNative(Class declClass, Member method, Object additionInfo); 62 | 63 | public static native void setObjectClassNative(Object object, Class parent); 64 | 65 | public static native Object cloneToSubclassNative(Object object, Class subClass); 66 | 67 | public static native void removeFinalFlagNative(Class cl); 68 | 69 | public static native void enforceDisableHiddenAPIPolicy(); 70 | 71 | private static native void reserved0(); 72 | 73 | private static native void reserved1(); 74 | } 75 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/java/com/lody/whale/xposed/XC_MethodReplacement.java: -------------------------------------------------------------------------------- 1 | package com.lody.whale.xposed; 2 | 3 | import com.lody.whale.xposed.callbacks.XCallback; 4 | 5 | /** 6 | * A special case of {@link XC_MethodHook} which completely replaces the original method. 7 | */ 8 | @SuppressWarnings({"unused", "WeakerAccess"}) 9 | public abstract class XC_MethodReplacement extends XC_MethodHook { 10 | /** 11 | * Creates a new callback with default priority. 12 | */ 13 | public XC_MethodReplacement() { 14 | super(); 15 | } 16 | 17 | /** 18 | * Creates a new callback with a specific priority. 19 | * 20 | * @param priority See {@link XCallback#priority}. 21 | */ 22 | public XC_MethodReplacement(final int priority) { 23 | super(priority); 24 | } 25 | 26 | @Override 27 | protected final void beforeHookedMethod(final MethodHookParam param) throws Throwable { 28 | try { 29 | param.setResult(replaceHookedMethod(param)); 30 | } catch (final Throwable t) { 31 | param.setThrowable(t); 32 | } 33 | } 34 | 35 | /** 36 | * @hide 37 | */ 38 | @Override 39 | @SuppressWarnings("all") 40 | protected final void afterHookedMethod(final MethodHookParam param) throws Throwable { 41 | } 42 | 43 | /** 44 | * Shortcut for replacing a method completely. Whatever is returned/thrown here is taken 45 | * instead of the result of the original method (which will not be called). 46 | *

47 | *

Note that implementations shouldn't call {@code super(param)}, it's not necessary. 48 | * 49 | * @param param Information about the method call. 50 | * @throws Throwable Anything that is thrown by the callback will be passed on to the original caller. 51 | */ 52 | @SuppressWarnings("all") 53 | protected abstract Object replaceHookedMethod(final MethodHookParam param) throws Throwable; 54 | 55 | /** 56 | * Predefined callback that skips the method without replacements. 57 | */ 58 | public static final XC_MethodReplacement DO_NOTHING = new XC_MethodReplacement(PRIORITY_HIGHEST * 2) { 59 | @Override 60 | protected Object replaceHookedMethod(final MethodHookParam param) throws Throwable { 61 | return null; 62 | } 63 | }; 64 | 65 | /** 66 | * Creates a callback which always returns a specific value. 67 | * 68 | * @param result The value that should be returned to callers of the hooked method. 69 | */ 70 | public static XC_MethodReplacement returnConstant(final Object result) { 71 | return returnConstant(XCallback.PRIORITY_DEFAULT, result); 72 | } 73 | 74 | /** 75 | * Like {@link #returnConstant(Object)}, but allows to specify a priority for the callback. 76 | * 77 | * @param priority See {@link XCallback#priority}. 78 | * @param result The value that should be returned to callers of the hooked method. 79 | */ 80 | public static XC_MethodReplacement returnConstant(final int priority, final Object result) { 81 | return new XC_MethodReplacement(priority) { 82 | @Override 83 | protected Object replaceHookedMethod(final MethodHookParam param) throws Throwable { 84 | return result; 85 | } 86 | }; 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/include/whale.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_PUBLIC_H_ 2 | #define WHALE_PUBLIC_H_ 3 | 4 | #define NULLABLE 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif // __cplusplus 9 | 10 | void WInlineHookFunction(void *address, void *replace, void **backup); 11 | 12 | void WImportHookFunction(const char *name, NULLABLE const char *libname, void *replace, void **backup); 13 | 14 | void *WDynamicLibOpen(const char *name); 15 | 16 | void *WDynamicLibOpenAlias(const char *name, const char *path); 17 | 18 | void *WDynamicLibSymbol(void *handle, const char *name); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif // __cplusplus 23 | #endif // WHALE_PUBLIC_H_ 24 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/android_build.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ANDROID_BUILD_H_ 2 | #define WHALE_ANDROID_ANDROID_BUILD_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define ANDROID_ICE_CREAM_SANDWICH 14 9 | #define ANDROID_ICE_CREAM_SANDWICH_MR1 15 10 | #define ANDROID_JELLY_BEAN 16 11 | #define ANDROID_JELLY_BEAN_MR1 17 12 | #define ANDROID_JELLY_BEAN_MR2 18 13 | #define ANDROID_KITKAT 19 14 | #define ANDROID_KITKAT_WATCH 20 15 | #define ANDROID_LOLLIPOP 21 16 | #define ANDROID_LOLLIPOP_MR1 22 17 | #define ANDROID_M 23 18 | #define ANDROID_N 24 19 | #define ANDROID_N_MR1 25 20 | #define ANDROID_O 26 21 | #define ANDROID_O_MR1 27 22 | #define ANDROID_P 28 23 | 24 | static inline int32_t GetAndroidApiLevel() { 25 | char prop_value[PROP_VALUE_MAX]; 26 | __system_property_get("ro.build.version.sdk", prop_value); 27 | return atoi(prop_value); 28 | } 29 | 30 | #endif // WHALE_ANDROID_ANDROID_BUILD_H_ 31 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/art_hook_param.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_INTERCEPT_PARAM_H_ 2 | #define WHALE_ANDROID_ART_INTERCEPT_PARAM_H_ 3 | 4 | #include 5 | #include "base/primitive_types.h" 6 | #include "ffi_cxx.h" 7 | 8 | namespace whale { 9 | namespace art { 10 | 11 | struct ArtHookParam final { 12 | bool is_static_; 13 | const char *shorty_; 14 | jobject addition_info_; 15 | ptr_t origin_compiled_code_; 16 | ptr_t origin_jni_code_; 17 | u4 origin_access_flags; 18 | u4 origin_code_item_off; 19 | jobject origin_method_; 20 | jobject hooked_method_; 21 | volatile ptr_t decl_class_; 22 | jobject class_Loader_; 23 | jmethodID hooked_native_method_; 24 | jmethodID origin_native_method_; 25 | FFIClosure *jni_closure_; 26 | }; 27 | 28 | } // namespace art 29 | } // namespace whale 30 | 31 | #endif // WHALE_ANDROID_ART_INTERCEPT_PARAM_H_ 32 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/art_jni_trampoline.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_JNI_TRAMPOLINE_H_ 2 | #define WHALE_ANDROID_ART_JNI_TRAMPOLINE_H_ 3 | 4 | #include "android/art/art_hook_param.h" 5 | 6 | namespace whale { 7 | namespace art { 8 | 9 | 10 | void BuildJniClosure(ArtHookParam *param); 11 | 12 | 13 | } // namespace art 14 | } // namespace whale 15 | 16 | #endif // WHALE_ANDROID_ART_JNI_TRAMPOLINE_H_ 17 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/art_method.cc: -------------------------------------------------------------------------------- 1 | #include "android/art/art_method.h" 2 | #include "well_known_classes.h" 3 | 4 | namespace whale { 5 | namespace art { 6 | 7 | jobject ArtMethod::Clone(JNIEnv *env, u4 access_flags) { 8 | int32_t api_level = GetAndroidApiLevel(); 9 | jmethodID jni_clone_method = nullptr; 10 | if (api_level < ANDROID_M) { 11 | jni_clone_method = 12 | reinterpret_cast(ArtRuntime::Get()->CloneArtObject(jni_method_)); 13 | } else { 14 | jni_clone_method = reinterpret_cast(malloc(offset_->method_size_)); 15 | if (symbols_->ArtMethod_CopyFrom) { 16 | symbols_->ArtMethod_CopyFrom(jni_clone_method, jni_method_, sizeof(ptr_t)); 17 | } else { 18 | memcpy(jni_clone_method, jni_method_, offset_->method_size_); 19 | } 20 | } 21 | 22 | ArtMethod clone_method = ArtMethod(jni_clone_method); 23 | bool is_direct_method = (access_flags & kAccDirectFlags) != 0; 24 | bool is_native_method = (access_flags & kAccNative) != 0; 25 | if (!is_direct_method) { 26 | access_flags &= ~(kAccPublic | kAccProtected); 27 | access_flags |= kAccPrivate; 28 | } 29 | access_flags &= ~kAccSynchronized; 30 | if (api_level < ANDROID_O_MR1) { 31 | access_flags |= kAccCompileDontBother_N; 32 | } else { 33 | access_flags |= kAccCompileDontBother_O_MR1; 34 | access_flags |= kAccPreviouslyWarm_O_MR1; 35 | } 36 | if (!is_native_method) { 37 | access_flags |= kAccSkipAccessChecks; 38 | } 39 | if (api_level >= ANDROID_N) { 40 | clone_method.SetHotnessCount(0); 41 | if (!is_native_method) { 42 | ptr_t profiling_info = GetEntryPointFromJni(); 43 | if (profiling_info != nullptr) { 44 | offset_t end = sizeof(u4) * 4; 45 | for (offset_t offset = 0; offset != end; offset += sizeof(u4)) { 46 | if (MemberOf(profiling_info, offset) == jni_method_) { 47 | AssignOffset(profiling_info, offset, jni_clone_method); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | if (!is_native_method && symbols_->art_quick_to_interpreter_bridge) { 54 | clone_method.SetEntryPointFromQuickCompiledCode( 55 | symbols_->art_quick_to_interpreter_bridge); 56 | } 57 | 58 | clone_method.SetAccessFlags(access_flags); 59 | 60 | bool is_constructor = (access_flags & kAccConstructor) != 0; 61 | bool is_static = (access_flags & kAccStatic) != 0; 62 | if (is_constructor) { 63 | clone_method.RemoveAccessFlags(kAccConstructor); 64 | } 65 | jobject java_method = env->ToReflectedMethod(WellKnownClasses::java_lang_Object, 66 | jni_clone_method, 67 | static_cast(is_static)); 68 | env->CallVoidMethod(java_method, 69 | WellKnownClasses::java_lang_reflect_AccessibleObject_setAccessible, 70 | true); 71 | if (is_constructor) { 72 | clone_method.AddAccessFlags(kAccConstructor); 73 | } 74 | return java_method; 75 | } 76 | 77 | 78 | } // namespace art 79 | } // namespace whale 80 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/art_symbol_resolver.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_SYMBOL_RESOLVER_H_ 2 | #define WHALE_ANDROID_ART_SYMBOL_RESOLVER_H_ 3 | 4 | #include 5 | #include "platform/linux/elf_image.h" 6 | #include "base/primitive_types.h" 7 | 8 | namespace whale { 9 | namespace art { 10 | 11 | struct ResolvedSymbols { 12 | const char *(*Art_GetMethodShorty)(JNIEnv *, jmethodID); 13 | 14 | void (*Dbg_SuspendVM)(); 15 | 16 | void (*Dbg_ResumeVM)(); 17 | 18 | void *art_quick_to_interpreter_bridge; 19 | void *artInterpreterToCompiledCodeBridge; 20 | 21 | void (*ProfileSaver_ForceProcessProfiles)(); 22 | 23 | void (*ArtMethod_CopyFrom)(jmethodID this_ptr, jmethodID from, size_t num_bytes); 24 | 25 | ptr_t (*Thread_DecodeJObject)(ptr_t thread, jobject obj); 26 | 27 | ptr_t (*Object_Clone)(ptr_t object_this, ptr_t thread); 28 | 29 | ptr_t (*Object_CloneWithClass)(ptr_t object_this, ptr_t thread, ptr_t cls); 30 | 31 | ptr_t (*Object_CloneWithSize)(ptr_t object_this, ptr_t thread, size_t num_bytes); 32 | 33 | jobject (*JniEnvExt_NewLocalRef)(JNIEnv *jnienv_ext_this, ptr_t art_object); 34 | 35 | }; 36 | 37 | class ArtSymbolResolver { 38 | public: 39 | ArtSymbolResolver() = default; 40 | 41 | bool Resolve(void *elf_image, s4 api_level); 42 | 43 | ResolvedSymbols *GetSymbols() { 44 | return &symbols_; 45 | }; 46 | 47 | private: 48 | ResolvedSymbols symbols_; 49 | }; 50 | 51 | } // namespace art 52 | } // namespace whale 53 | 54 | #endif // WHALE_ANDROID_ART_SYMBOL_RESOLVER_H_ 55 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/java_types.cc: -------------------------------------------------------------------------------- 1 | #include "android/art/java_types.h" 2 | 3 | namespace whale { 4 | namespace art { 5 | 6 | #define EXPORT_LANG_ClASS(c) jclass Types::java_lang_##c; jmethodID Types::java_lang_##c##_init; jmethodID Types::java_value_##c; 7 | 8 | EXPORT_LANG_ClASS(Integer); 9 | EXPORT_LANG_ClASS(Long); 10 | EXPORT_LANG_ClASS(Float); 11 | EXPORT_LANG_ClASS(Double); 12 | EXPORT_LANG_ClASS(Byte); 13 | EXPORT_LANG_ClASS(Short); 14 | EXPORT_LANG_ClASS(Boolean); 15 | EXPORT_LANG_ClASS(Character); 16 | 17 | #undef EXPORT_LANG_ClASS 18 | 19 | void Types::Load(JNIEnv *env) { 20 | jclass clazz; 21 | env->PushLocalFrame(16); 22 | 23 | #define LOAD_CLASS(c, s) clazz = env->FindClass(s); c = reinterpret_cast(env->NewWeakGlobalRef(clazz)) 24 | #define LOAD_LANG_CLASS(c, s) LOAD_CLASS(java_lang_##c, "java/lang/" #c); java_lang_##c##_init = env->GetMethodID(java_lang_##c, "", s) 25 | 26 | LOAD_LANG_CLASS(Integer, "(I)V"); 27 | LOAD_LANG_CLASS(Long, "(J)V"); 28 | LOAD_LANG_CLASS(Float, "(F)V"); 29 | LOAD_LANG_CLASS(Double, "(D)V"); 30 | LOAD_LANG_CLASS(Byte, "(B)V"); 31 | LOAD_LANG_CLASS(Short, "(S)V"); 32 | LOAD_LANG_CLASS(Boolean, "(Z)V"); 33 | LOAD_LANG_CLASS(Character, "(C)V"); 34 | 35 | #undef LOAD_CLASS 36 | #undef LOAD_LANG_CLASS 37 | 38 | #define LOAD_METHOD(k, c, r, s) java_value_##c = env->GetMethodID(k, r "Value", s) 39 | #define LOAD_NUMBER(c, r, s) LOAD_METHOD(java_lang_Number, c, r, s) 40 | 41 | jclass java_lang_Number = env->FindClass("java/lang/Number"); 42 | 43 | LOAD_NUMBER(Integer, "int", "()I"); 44 | LOAD_NUMBER(Long, "long", "()J"); 45 | LOAD_NUMBER(Float, "float", "()F"); 46 | LOAD_NUMBER(Double, "double", "()D"); 47 | LOAD_NUMBER(Byte, "byte", "()B"); 48 | LOAD_NUMBER(Short, "short", "()S"); 49 | 50 | LOAD_METHOD(java_lang_Boolean, Boolean, "boolean", "()Z"); 51 | LOAD_METHOD(java_lang_Character, Character, "char", "()C"); 52 | 53 | env->PopLocalFrame(nullptr); 54 | #undef LOAD_METHOD 55 | #undef LOAD_NUMBER 56 | } 57 | 58 | 59 | #define LANG_BOX(c, t) jobject Types::To##c(JNIEnv *env, t v) { \ 60 | return env->NewObject(Types::java_lang_##c, Types::java_lang_##c##_init, v); \ 61 | } 62 | #define LANG_UNBOX_V(k, c, t) t Types::From##c(JNIEnv *env, jobject j) { \ 63 | return env->Call##k##Method(j, Types::java_value_##c); \ 64 | } 65 | #define LANG_UNBOX(c, t) LANG_UNBOX_V(c, c, t) 66 | 67 | LANG_BOX(Integer, jint); 68 | LANG_BOX(Long, jlong); 69 | LANG_BOX(Float, jfloat); 70 | LANG_BOX(Double, jdouble); 71 | LANG_BOX(Byte, jbyte); 72 | LANG_BOX(Short, jshort); 73 | LANG_BOX(Boolean, jboolean); 74 | LANG_BOX(Character, jchar); 75 | 76 | jobject Types::ToObject(JNIEnv *env, jobject obj) { 77 | return obj; 78 | } 79 | 80 | LANG_UNBOX_V(Int, Integer, jint); 81 | LANG_UNBOX(Long, jlong); 82 | LANG_UNBOX(Float, jfloat); 83 | LANG_UNBOX(Double, jdouble); 84 | LANG_UNBOX(Byte, jbyte); 85 | LANG_UNBOX(Short, jshort); 86 | LANG_UNBOX(Boolean, jboolean); 87 | LANG_UNBOX_V(Char, Character, jchar); 88 | 89 | jobject Types::FromObject(JNIEnv *env, jobject obj) { 90 | return obj; 91 | } 92 | 93 | 94 | #undef LANG_BOX 95 | #undef LANG_UNBOX_V 96 | #undef LANG_UNBOX 97 | 98 | } // namespace art 99 | } // namespace whale 100 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/java_types.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_JAVA_TYPES_H_ 2 | #define WHALE_ANDROID_ART_JAVA_TYPES_H_ 3 | 4 | #include 5 | #include "android/art/art_runtime.h" 6 | 7 | 8 | namespace whale { 9 | namespace art { 10 | 11 | struct Types { 12 | #define LANG_ClASS(c) static jclass java_lang_##c; static jmethodID java_lang_##c##_init; static jmethodID java_value_##c; 13 | 14 | LANG_ClASS(Integer); 15 | LANG_ClASS(Long); 16 | LANG_ClASS(Float); 17 | LANG_ClASS(Double); 18 | LANG_ClASS(Byte); 19 | LANG_ClASS(Short); 20 | LANG_ClASS(Boolean); 21 | LANG_ClASS(Character); 22 | 23 | #undef LANG_ClASS 24 | static void Load(JNIEnv *env); 25 | 26 | 27 | #define LANG_BOX_DEF(c, t) static jobject To##c(JNIEnv *env, t v); 28 | 29 | #define LANG_UNBOX_V_DEF(k, c, t) static t From##c(JNIEnv *env, jobject j); 30 | 31 | #define LANG_UNBOX_DEF(c, t) LANG_UNBOX_V_DEF(c, c, t) 32 | 33 | LANG_BOX_DEF(Object, jobject); 34 | LANG_BOX_DEF(Integer, jint); 35 | LANG_BOX_DEF(Long, jlong); 36 | LANG_BOX_DEF(Float, jfloat); 37 | LANG_BOX_DEF(Double, jdouble); 38 | LANG_BOX_DEF(Byte, jbyte); 39 | LANG_BOX_DEF(Short, jshort); 40 | LANG_BOX_DEF(Boolean, jboolean); 41 | LANG_BOX_DEF(Character, jchar); 42 | 43 | LANG_UNBOX_V_DEF(Int, Integer, jint); 44 | LANG_UNBOX_DEF(Object, jobject); 45 | LANG_UNBOX_DEF(Long, jlong); 46 | LANG_UNBOX_DEF(Float, jfloat); 47 | LANG_UNBOX_DEF(Double, jdouble); 48 | LANG_UNBOX_DEF(Byte, jbyte); 49 | LANG_UNBOX_DEF(Short, jshort); 50 | LANG_UNBOX_DEF(Boolean, jboolean); 51 | LANG_UNBOX_V_DEF(Char, Character, jchar); 52 | 53 | #undef LANG_BOX_DEF 54 | #undef LANG_UNBOX_V_DEF 55 | #undef LANG_UNBOX_DEF 56 | }; 57 | 58 | } // namespace art 59 | } // namespace whale 60 | 61 | #endif // WHALE_ANDROID_ART_JAVA_TYPES_H_ 62 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/modifiers.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_MODIFIERS_H_ 2 | #define WHALE_ANDROID_ART_MODIFIERS_H_ 3 | 4 | #include "base/primitive_types.h" 5 | 6 | namespace whale { 7 | namespace art { 8 | 9 | static constexpr u4 kAccPublic = 0x0001; // class, field, method, ic 10 | static constexpr u4 kAccPrivate = 0x0002; // field, method, ic 11 | static constexpr u4 kAccProtected = 0x0004; // field, method, ic 12 | static constexpr u4 kAccStatic = 0x0008; // field, method, ic 13 | static constexpr u4 kAccFinal = 0x0010; // class, field, method, ic 14 | static constexpr u4 kAccSynchronized = 0x0020; // method (only allowed on natives) 15 | static constexpr u4 kAccSuper = 0x0020; // class (not used in dex) 16 | static constexpr u4 kAccVolatile = 0x0040; // field 17 | static constexpr u4 kAccBridge = 0x0040; // method (1.5) 18 | static constexpr u4 kAccTransient = 0x0080; // field 19 | static constexpr u4 kAccVarargs = 0x0080; // method (1.5) 20 | static constexpr u4 kAccNative = 0x0100; // method 21 | static constexpr u4 kAccInterface = 0x0200; // class, ic 22 | static constexpr u4 kAccAbstract = 0x0400; // class, method, ic 23 | static constexpr u4 kAccStrict = 0x0800; // method 24 | static constexpr u4 kAccSynthetic = 0x1000; // class, field, method, ic 25 | static constexpr u4 kAccAnnotation = 0x2000; // class, ic (1.5) 26 | static constexpr u4 kAccEnum = 0x4000; // class, field, ic (1.5) 27 | 28 | static constexpr u4 kAccJavaFlagsMask = 0xffff; // bits set from Java sources (low 16) 29 | 30 | static constexpr u4 kAccConstructor = 0x00010000; // method (dex only) <(cl)init> 31 | static constexpr u4 kAccDeclaredSynchronized = 0x00020000; // method (dex only) 32 | static constexpr u4 kAccClassIsProxy = 0x00040000; // class (dex only) 33 | // Set to indicate that the ArtMethod is obsolete and has a different DexCache + DexFile from its 34 | // declaring class. This flag may only be applied to methods. 35 | static constexpr u4 kAccObsoleteMethod = 0x00040000; // method (runtime) 36 | 37 | static constexpr uint32_t kAccFastNative = 0x00080000u; // method (dex only) 38 | static constexpr uint32_t kAccPreverified = kAccFastNative; // class (runtime) 39 | static constexpr uint32_t kAccSkipAccessChecks = kAccPreverified; 40 | static constexpr uint32_t kAccCriticalNative_P = 0x00200000; // method (runtime; native only) 41 | // Android M only 42 | static constexpr uint32_t kAccDontInline = 0x00400000u; // method (dex only) 43 | // Android N or later. Set by the verifier for a method we do not want the compiler to compile. 44 | static constexpr uint32_t kAccCompileDontBother_N = 0x01000000u; // method (runtime) 45 | // Android O MR1 or later. Set by the verifier for a method we do not want the compiler to compile. 46 | static constexpr uint32_t kAccCompileDontBother_O_MR1 = 0x02000000; // method (runtime) 47 | // Set by the JIT when clearing profiling infos to denote that a method was previously warm. 48 | static constexpr uint32_t kAccPreviouslyWarm_O_MR1 = 0x00800000; // method (runtime) 49 | 50 | static constexpr uint32_t kAccDirectFlags = kAccStatic | kAccPrivate | kAccConstructor; 51 | 52 | static constexpr uint32_t kAccPublicApi = 0x10000000; // field, method 53 | static constexpr uint32_t kAccHiddenapiBits = 0x30000000; // field, method 54 | 55 | } // namespace art 56 | } // namespace whale 57 | 58 | #endif // WHALE_ANDROID_ART_MODIFIERS_H_ 59 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/native_on_load.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_NATIVE_ON_LOAD_H_ 2 | #define WHALE_ANDROID_ART_NATIVE_ON_LOAD_H_ 3 | 4 | #include 5 | 6 | constexpr const char *kMethodReserved0 = "reserved0"; 7 | constexpr const char *kMethodReserved1 = "reserved1"; 8 | 9 | /** 10 | * DO NOT rename the following function 11 | */ 12 | extern "C" { 13 | 14 | void WhaleRuntime_reserved0(JNIEnv *env, jclass cl); 15 | 16 | void WhaleRuntime_reserved1(JNIEnv *env, jclass cl); 17 | 18 | } 19 | 20 | #ifndef WHALE_ANDROID_AUTO_LOAD 21 | JNIEXPORT jint JNICALL Whale_OnLoad(JavaVM *vm, void *reserved); 22 | #endif 23 | 24 | 25 | #endif // WHALE_ANDROID_ART_NATIVE_ON_LOAD_H_ 26 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/scoped_thread_state_change.cc: -------------------------------------------------------------------------------- 1 | #include "android/jni_helper.h" 2 | #include "android/android_build.h" 3 | #include "android/art/scoped_thread_state_change.h" 4 | #include "art_runtime.h" 5 | 6 | namespace whale { 7 | namespace art { 8 | 9 | static volatile long kNoGCDaemonsGuard = 0; 10 | 11 | jclass ScopedNoGCDaemons::java_lang_Daemons; 12 | jmethodID ScopedNoGCDaemons::java_lang_Daemons_start; 13 | jmethodID ScopedNoGCDaemons::java_lang_Daemons_stop; 14 | 15 | void ScopedNoGCDaemons::Load(JNIEnv *env) { 16 | java_lang_Daemons = reinterpret_cast(env->NewGlobalRef( 17 | env->FindClass("java/lang/Daemons"))); 18 | if (java_lang_Daemons == nullptr) { 19 | JNIExceptionClear(env); 20 | LOG(WARNING) << "java/lang/Daemons API is unavailable."; 21 | return; 22 | } 23 | java_lang_Daemons_start = env->GetStaticMethodID(java_lang_Daemons, "start", "()V"); 24 | if (java_lang_Daemons_start == nullptr) { 25 | JNIExceptionClear(env); 26 | java_lang_Daemons_start = env->GetStaticMethodID(java_lang_Daemons, "startPostZygoteFork", 27 | "()V"); 28 | } 29 | if (java_lang_Daemons_start == nullptr) { 30 | LOG(WARNING) 31 | << "java/lang/Daemons API is available but no start/startPostZygoteFork method."; 32 | JNIExceptionClear(env); 33 | } 34 | java_lang_Daemons_stop = env->GetStaticMethodID(java_lang_Daemons, "stop", "()V"); 35 | JNIExceptionClear(env); 36 | } 37 | 38 | ScopedNoGCDaemons::ScopedNoGCDaemons(JNIEnv *env) : env_(env) { 39 | if (java_lang_Daemons_start != nullptr) { 40 | if (__sync_sub_and_fetch(&kNoGCDaemonsGuard, 1) <= 0) { 41 | env_->CallStaticVoidMethod(java_lang_Daemons, java_lang_Daemons_stop); 42 | JNIExceptionClear(env_); 43 | } 44 | } 45 | } 46 | 47 | 48 | ScopedNoGCDaemons::~ScopedNoGCDaemons() { 49 | if (java_lang_Daemons_stop != nullptr) { 50 | if (__sync_add_and_fetch(&kNoGCDaemonsGuard, 1) == 1) { 51 | env_->CallStaticVoidMethod(java_lang_Daemons, java_lang_Daemons_start); 52 | JNIExceptionClear(env_); 53 | } 54 | } 55 | } 56 | 57 | ScopedSuspendAll::ScopedSuspendAll() { 58 | ResolvedSymbols *symbols = art::ArtRuntime::Get()->GetSymbols(); 59 | if (symbols->Dbg_SuspendVM && symbols->Dbg_ResumeVM) { 60 | symbols->Dbg_SuspendVM(); 61 | } else { 62 | LOG(WARNING) << "Suspend VM API is unavailable."; 63 | } 64 | } 65 | 66 | ScopedSuspendAll::~ScopedSuspendAll() { 67 | ResolvedSymbols *symbols = art::ArtRuntime::Get()->GetSymbols(); 68 | if (symbols->Dbg_SuspendVM && symbols->Dbg_ResumeVM) { 69 | symbols->Dbg_ResumeVM(); 70 | } 71 | } 72 | 73 | 74 | } // namespace art 75 | } // namespace whale 76 | 77 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/scoped_thread_state_change.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART__SCOPED_THREAD_STATE_CHANGE_H_ 2 | #define WHALE_ANDROID_ART__SCOPED_THREAD_STATE_CHANGE_H_ 3 | 4 | #include 5 | 6 | namespace whale { 7 | namespace art { 8 | 9 | class ScopedNoGCDaemons { 10 | static jclass java_lang_Daemons; 11 | static jmethodID java_lang_Daemons_start; 12 | static jmethodID java_lang_Daemons_stop; 13 | 14 | public: 15 | static void Load(JNIEnv *env); 16 | 17 | ScopedNoGCDaemons(JNIEnv *env); 18 | 19 | ~ScopedNoGCDaemons(); 20 | 21 | private: 22 | JNIEnv *env_; 23 | }; 24 | 25 | class ScopedSuspendAll { 26 | public: 27 | ScopedSuspendAll(); 28 | 29 | ~ScopedSuspendAll(); 30 | }; 31 | 32 | 33 | } // namespace art 34 | } // namespace whale 35 | 36 | #endif // WHALE_ANDROID_ART__SCOPED_THREAD_STATE_CHANGE_H_ 37 | 38 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/art/well_known_classes.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_WELL_KNOWN_CLASSES_H_ 2 | #define WHALE_ANDROID_ART_WELL_KNOWN_CLASSES_H_ 3 | 4 | #include 5 | 6 | namespace whale { 7 | namespace art { 8 | 9 | struct WellKnownClasses { 10 | static void Load(JNIEnv *env); 11 | 12 | static jclass java_lang_Object; 13 | static jclass java_lang_reflect_Method; 14 | static jclass java_lang_Class; 15 | static jclass java_lang_ClassLoader; 16 | static jclass java_lang_reflect_AccessibleObject; 17 | static jclass java_lang_Thread; 18 | static jclass java_lang_IllegalArgumentException; 19 | 20 | static jmethodID java_lang_reflect_Method_invoke; 21 | static jmethodID java_lang_Class_getClassLoader; 22 | static jmethodID java_lang_reflect_AccessibleObject_setAccessible; 23 | static jmethodID java_lang_Thread_currentThread; 24 | 25 | static jfieldID java_lang_Thread_nativePeer; 26 | }; 27 | 28 | } // namespace art 29 | } // namespace whale 30 | 31 | #endif // WHALE_ANDROID_ART_WELL_KNOWN_CLASSES_H_ 32 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/android/jni_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ANDROID_ART_JNI_HELPER_H_ 2 | #define WHALE_ANDROID_ART_JNI_HELPER_H_ 3 | 4 | #include 5 | #include 6 | 7 | #define NATIVE_METHOD(className, functionName, signature) \ 8 | { #functionName, signature, reinterpret_cast(className ## _ ## functionName) } 9 | 10 | #define NELEM(x) (sizeof(x)/sizeof((x)[0])) 11 | 12 | #define JNI_START JNIEnv *env, jclass cl 13 | 14 | static inline void JNIExceptionClear(JNIEnv *env) { 15 | if (env->ExceptionCheck()) { 16 | env->ExceptionClear(); 17 | } 18 | } 19 | 20 | static inline bool JNIExceptionCheck(JNIEnv *env) { 21 | if (env->ExceptionCheck()) { 22 | jthrowable e = env->ExceptionOccurred(); 23 | env->Throw(e); 24 | env->DeleteLocalRef(e); 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | static inline void JNIExceptionClearAndDescribe(JNIEnv *env) { 31 | if (env->ExceptionCheck()) { 32 | env->ExceptionDescribe(); 33 | env->ExceptionClear(); 34 | } 35 | } 36 | 37 | template 38 | class ScopedLocalRef { 39 | public: 40 | ScopedLocalRef(JNIEnv *env, T localRef) : mEnv(env), mLocalRef(localRef) { 41 | } 42 | 43 | ~ScopedLocalRef() { 44 | reset(); 45 | } 46 | 47 | void reset(T ptr = nullptr) { 48 | if (ptr != mLocalRef) { 49 | if (mLocalRef != nullptr) { 50 | mEnv->DeleteLocalRef(mLocalRef); 51 | } 52 | mLocalRef = ptr; 53 | } 54 | } 55 | 56 | T release() { 57 | T localRef = mLocalRef; 58 | mLocalRef = nullptr; 59 | return localRef; 60 | } 61 | 62 | T get() const { 63 | return mLocalRef; 64 | } 65 | 66 | private: 67 | JNIEnv *const mEnv; 68 | T mLocalRef; 69 | 70 | DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef); 71 | }; 72 | 73 | #endif // WHALE_ANDROID_ART_JNI_HELPER_H_ 74 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/assembler.cc: -------------------------------------------------------------------------------- 1 | #include "assembler/assembler.h" 2 | 3 | namespace whale { 4 | 5 | 6 | AssemblerBuffer::AssemblerBuffer() { 7 | static const size_t kInitialBufferCapacity = 4 * KB; 8 | contents_ = reinterpret_cast(malloc(kInitialBufferCapacity)); 9 | cursor_ = contents_; 10 | limit_ = ComputeLimit(contents_, kInitialBufferCapacity); 11 | fixup_ = nullptr; 12 | slow_path_ = nullptr; 13 | has_ensured_capacity_ = false; 14 | fixups_processed_ = false; 15 | // Verify internal state. 16 | CHECK_EQ(Capacity(), kInitialBufferCapacity); 17 | CHECK_EQ(Size(), 0U); 18 | } 19 | 20 | 21 | AssemblerBuffer::~AssemblerBuffer() { 22 | free(contents_); 23 | } 24 | 25 | 26 | void AssemblerBuffer::ProcessFixups(const MemoryRegion ®ion) { 27 | AssemblerFixup *fixup = fixup_; 28 | while (fixup != nullptr) { 29 | fixup->Process(region, fixup->position()); 30 | fixup = fixup->previous(); 31 | } 32 | } 33 | 34 | 35 | void AssemblerBuffer::FinalizeInstructions(const MemoryRegion &instructions) { 36 | // Copy the instructions from the buffer. 37 | MemoryRegion from(reinterpret_cast(contents()), Size()); 38 | instructions.CopyFrom(0, from); 39 | // Process fixups in the instructions. 40 | ProcessFixups(instructions); 41 | fixups_processed_ = true; 42 | } 43 | 44 | 45 | void AssemblerBuffer::ExtendCapacity(size_t min_capacity) { 46 | size_t old_size = Size(); 47 | size_t old_capacity = Capacity(); 48 | DCHECK_GT(min_capacity, old_capacity); 49 | size_t new_capacity = std::min(old_capacity * 2, old_capacity + 1 * MB); 50 | new_capacity = std::max(new_capacity, min_capacity); 51 | 52 | // Allocate the new data area and copy contents of the old one to it. 53 | contents_ = reinterpret_cast(realloc(contents_, new_capacity)); 54 | 55 | // Update the cursor and recompute the limit. 56 | cursor_ = contents_ + old_size; 57 | limit_ = ComputeLimit(contents_, new_capacity); 58 | 59 | // Verify internal state. 60 | CHECK_EQ(Capacity(), new_capacity); 61 | CHECK_EQ(Size(), old_size); 62 | } 63 | 64 | } // namespace whale 65 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/label.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ASSEMBLER_LABEL_H_ 2 | #define WHALE_ASSEMBLER_LABEL_H_ 3 | 4 | #include 5 | #include "base/logging.h" 6 | 7 | namespace whale { 8 | 9 | class Assembler; 10 | 11 | class AssemblerBuffer; 12 | 13 | class AssemblerFixup; 14 | 15 | namespace x86 { 16 | class X86Assembler; 17 | 18 | class NearLabel; 19 | } // namespace x86 20 | namespace x86_64 { 21 | class X86_64Assembler; 22 | 23 | class NearLabel; 24 | } // namespace x86_64 25 | 26 | class ExternalLabel { 27 | public: 28 | ExternalLabel(const char *name_in, uintptr_t address_in) 29 | : name_(name_in), address_(address_in) { 30 | DCHECK(name_in != nullptr); 31 | } 32 | 33 | const char *name() const { return name_; } 34 | 35 | uintptr_t address() const { 36 | return address_; 37 | } 38 | 39 | private: 40 | const char *name_; 41 | const uintptr_t address_; 42 | }; 43 | 44 | class Label { 45 | public: 46 | Label() : position_(0) {} 47 | 48 | Label(Label &&src) 49 | : position_(src.position_) { 50 | // We must unlink/unbind the src label when moving; if not, calling the destructor on 51 | // the src label would fail. 52 | src.position_ = 0; 53 | } 54 | 55 | ~Label() { 56 | // Assert if label is being destroyed with unresolved branches pending. 57 | CHECK(!IsLinked()); 58 | } 59 | 60 | // Returns the position for bound and linked labels. Cannot be used 61 | // for unused labels. 62 | int Position() const { 63 | CHECK(!IsUnused()); 64 | return IsBound() ? -position_ - sizeof(void *) : position_ - sizeof(void *); 65 | } 66 | 67 | int LinkPosition() const { 68 | CHECK(IsLinked()); 69 | return position_ - sizeof(void *); 70 | } 71 | 72 | bool IsBound() const { return position_ < 0; } 73 | 74 | bool IsUnused() const { return position_ == 0; } 75 | 76 | bool IsLinked() const { return position_ > 0; } 77 | 78 | private: 79 | 80 | int position_; 81 | 82 | void Reinitialize() { 83 | position_ = 0; 84 | } 85 | 86 | void BindTo(int position) { 87 | position_ = -position - sizeof(void *); 88 | } 89 | 90 | void LinkTo(int position) { 91 | position_ = position + sizeof(void *); 92 | } 93 | 94 | friend class x86::X86Assembler; 95 | 96 | friend class x86::NearLabel; 97 | 98 | friend class x86_64::X86_64Assembler; 99 | 100 | friend class x86_64::NearLabel; 101 | 102 | DISALLOW_COPY_AND_ASSIGN(Label); 103 | }; 104 | 105 | 106 | } // namespace whale 107 | 108 | #endif // WHALE_ASSEMBLER_LABEL_H_ 109 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/managed_register.h: -------------------------------------------------------------------------------- 1 | #ifndef MYAPPLICATION_MANAGED_REGISTER_H 2 | #define MYAPPLICATION_MANAGED_REGISTER_H 3 | 4 | #include "assembler/value_object.h" 5 | 6 | namespace whale { 7 | 8 | class ManagedRegister : public ValueObject { 9 | public: 10 | // ManagedRegister is a value class. There exists no method to change the 11 | // internal state. We therefore allow a copy constructor and an 12 | // assignment-operator. 13 | constexpr ManagedRegister(const ManagedRegister &other) = default; 14 | 15 | ManagedRegister &operator=(const ManagedRegister &other) = default; 16 | 17 | // It is valid to invoke Equals on and with a NoRegister. 18 | constexpr bool Equals(const ManagedRegister &other) const { 19 | return id_ == other.id_; 20 | } 21 | 22 | constexpr bool IsNoRegister() const { 23 | return id_ == kNoRegister; 24 | } 25 | 26 | static constexpr ManagedRegister NoRegister() { 27 | return ManagedRegister(); 28 | } 29 | 30 | constexpr int RegId() const { return id_; } 31 | 32 | explicit constexpr ManagedRegister(int reg_id) : id_(reg_id) {} 33 | 34 | protected: 35 | static const int kNoRegister = -1; 36 | 37 | constexpr ManagedRegister() : id_(kNoRegister) {} 38 | 39 | int id_; 40 | }; 41 | 42 | } // namespace whale 43 | 44 | #endif //MYAPPLICATION_MANAGED_REGISTER_H 45 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/memory_region.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "assembler/memory_region.h" 3 | 4 | namespace whale { 5 | 6 | void MemoryRegion::CopyFrom(size_t offset, const MemoryRegion &from) const { 7 | CHECK(from.pointer() != nullptr); 8 | CHECK_GT(from.size(), 0U); 9 | CHECK_GE(this->size(), from.size()); 10 | CHECK_LE(offset, this->size() - from.size()); 11 | memmove(reinterpret_cast(begin() + offset), from.pointer(), from.size()); 12 | } 13 | 14 | } // namespace whale 15 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/value_object.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ASSEMBLER_VALUE_OBJECT_H_ 2 | #define WHALE_ASSEMBLER_VALUE_OBJECT_H_ 3 | 4 | #include "base/macros.h" 5 | 6 | namespace whale { 7 | 8 | class ValueObject { 9 | private: 10 | DISALLOW_ALLOCATION(); 11 | }; 12 | 13 | } // namespace whale 14 | 15 | #endif // WHALE_ASSEMBLER_VALUE_OBJECT_H_ 16 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/vixl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_STANDARD 14) 2 | 3 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -fdiagnostics-show-option -Wextra -Wredundant-decls -pedantic -Wwrite-strings -Wunused") 4 | 5 | add_definitions(-DVIXL_CODE_BUFFER_MALLOC) 6 | 7 | set(VIXL_SOURCES 8 | code-buffer-vixl.cc 9 | compiler-intrinsics-vixl.cc 10 | cpu-features.cc 11 | utils-vixl.cc) 12 | 13 | set(VIXL_AARCH32 14 | aarch32/assembler-aarch32.cc 15 | aarch32/constants-aarch32.cc 16 | aarch32/instructions-aarch32.cc 17 | aarch32/location-aarch32.cc 18 | aarch32/macro-assembler-aarch32.cc 19 | aarch32/operands-aarch32.cc 20 | ) 21 | 22 | set(VIXL_AARCH64 23 | aarch64/assembler-aarch64.cc 24 | aarch64/cpu-aarch64.cc 25 | aarch64/cpu-features-auditor-aarch64.cc 26 | aarch64/decoder-aarch64.cc 27 | aarch64/instructions-aarch64.cc 28 | aarch64/instrument-aarch64.cc 29 | aarch64/logic-aarch64.cc 30 | aarch64/macro-assembler-aarch64.cc 31 | aarch64/operands-aarch64.cc 32 | aarch64/pointer-auth-aarch64.cc 33 | aarch64/simulator-aarch64.cc 34 | ) 35 | 36 | 37 | if (ENABLE_SIMULATOR) 38 | add_definitions(-DVIXL_INCLUDE_SIMULATOR_AARCH64) 39 | set(VIXL_SOURCES ${VIXL_SOURCES} ${VIXL_AARCH32} ${VIXL_AARCH64}) 40 | endif () 41 | 42 | if (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") 43 | add_definitions("-DVIXL_INCLUDE_TARGET_A32") 44 | add_definitions("-DVIXL_INCLUDE_TARGET_T32") 45 | set(VIXL_SOURCES ${VIXL_SOURCES} ${VIXL_AARCH32}) 46 | elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") 47 | set(VIXL_SOURCES ${VIXL_SOURCES} ${VIXL_AARCH64}) 48 | endif () 49 | 50 | if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|aarch64)") 51 | add_library(vixl ${VIXL_SOURCES}) 52 | endif () 53 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/vixl/platform-vixl.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014, VIXL authors 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are met: 6 | // 7 | // * Redistributions of source code must retain the above copyright notice, 8 | // this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, 10 | // this list of conditions and the following disclaimer in the documentation 11 | // and/or other materials provided with the distribution. 12 | // * Neither the name of ARM Limited nor the names of its contributors may be 13 | // used to endorse or promote products derived from this software without 14 | // specific prior written permission. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | #ifndef PLATFORM_H 28 | #define PLATFORM_H 29 | 30 | // Define platform specific functionalities. 31 | extern "C" { 32 | #include 33 | } 34 | 35 | namespace vixl { 36 | inline void HostBreakpoint() { raise(SIGINT); } 37 | } // namespace vixl 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/x86/constants_x86.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ASSEMBLER_CONSTANTS_X86_H_ 2 | #define WHALE_ASSEMBLER_CONSTANTS_X86_H_ 3 | 4 | #include 5 | #include "base/macros.h" 6 | 7 | namespace whale { 8 | namespace x86 { 9 | 10 | 11 | enum ByteRegister { 12 | AL = 0, 13 | CL = 1, 14 | DL = 2, 15 | BL = 3, 16 | AH = 4, 17 | CH = 5, 18 | DH = 6, 19 | BH = 7, 20 | kNoByteRegister = -1 // Signals an illegal register. 21 | }; 22 | 23 | enum X87Register { 24 | ST0 = 0, 25 | ST1 = 1, 26 | ST2 = 2, 27 | ST3 = 3, 28 | ST4 = 4, 29 | ST5 = 5, 30 | ST6 = 6, 31 | ST7 = 7, 32 | kNumberOfX87Registers = 8, 33 | kNoX87Register = -1 // Signals an illegal register. 34 | }; 35 | 36 | enum ScaleFactor { 37 | TIMES_1 = 0, 38 | TIMES_2 = 1, 39 | TIMES_4 = 2, 40 | TIMES_8 = 3 41 | }; 42 | 43 | enum Condition { 44 | kOverflow = 0, 45 | kNoOverflow = 1, 46 | kBelow = 2, 47 | kAboveEqual = 3, 48 | kEqual = 4, 49 | kNotEqual = 5, 50 | kBelowEqual = 6, 51 | kAbove = 7, 52 | kSign = 8, 53 | kNotSign = 9, 54 | kParityEven = 10, 55 | kParityOdd = 11, 56 | kLess = 12, 57 | kGreaterEqual = 13, 58 | kLessEqual = 14, 59 | kGreater = 15, 60 | 61 | kZero = kEqual, 62 | kNotZero = kNotEqual, 63 | kNegative = kSign, 64 | kPositive = kNotSign, 65 | kCarrySet = kBelow, 66 | kCarryClear = kAboveEqual, 67 | kUnordered = kParityEven 68 | }; 69 | 70 | 71 | class Instr { 72 | public: 73 | static const uint8_t kHltInstruction = 0xF4; 74 | // We prefer not to use the int3 instruction since it conflicts with gdb. 75 | static const uint8_t kBreakPointInstruction = kHltInstruction; 76 | 77 | bool IsBreakPoint() { 78 | return (*reinterpret_cast(this)) == kBreakPointInstruction; 79 | } 80 | 81 | // Instructions are read out of a code stream. The only way to get a 82 | // reference to an instruction is to convert a pointer. There is no way 83 | // to allocate or create instances of class Instr. 84 | // Use the At(pc) function to create references to Instr. 85 | static Instr *At(uintptr_t pc) { return reinterpret_cast(pc); } 86 | 87 | private: 88 | DISALLOW_IMPLICIT_CONSTRUCTORS(Instr); 89 | }; 90 | 91 | } // namespace x86 92 | } // namespace whale 93 | 94 | #endif // WHALE_ASSEMBLER_CONSTANTS_X86_H_ 95 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/x86/managed_register_x86.cc: -------------------------------------------------------------------------------- 1 | #include "assembler/x86/managed_register_x86.h" 2 | 3 | namespace whale { 4 | namespace x86 { 5 | 6 | // Define register pairs. 7 | // This list must be kept in sync with the RegisterPair enum. 8 | #define REGISTER_PAIR_LIST(P) \ 9 | P(EAX, EDX) \ 10 | P(EAX, ECX) \ 11 | P(EAX, EBX) \ 12 | P(EAX, EDI) \ 13 | P(EDX, ECX) \ 14 | P(EDX, EBX) \ 15 | P(EDX, EDI) \ 16 | P(ECX, EBX) \ 17 | P(ECX, EDI) \ 18 | P(EBX, EDI) \ 19 | P(ECX, EDX) 20 | 21 | 22 | struct RegisterPairDescriptor { 23 | RegisterPair reg; // Used to verify that the enum is in sync. 24 | Register low; 25 | Register high; 26 | }; 27 | 28 | 29 | static const RegisterPairDescriptor kRegisterPairs[] = { 30 | #define REGISTER_PAIR_ENUMERATION(low, high) { low##_##high, low, high }, 31 | REGISTER_PAIR_LIST(REGISTER_PAIR_ENUMERATION) 32 | #undef REGISTER_PAIR_ENUMERATION 33 | }; 34 | 35 | 36 | bool X86ManagedRegister::Overlaps(const X86ManagedRegister &other) const { 37 | if (IsNoRegister() || other.IsNoRegister()) return false; 38 | CHECK(IsValidManagedRegister()); 39 | CHECK(other.IsValidManagedRegister()); 40 | if (Equals(other)) return true; 41 | if (IsRegisterPair()) { 42 | Register low = AsRegisterPairLow(); 43 | Register high = AsRegisterPairHigh(); 44 | return X86ManagedRegister::FromCpuRegister(low).Overlaps(other) || 45 | X86ManagedRegister::FromCpuRegister(high).Overlaps(other); 46 | } 47 | if (other.IsRegisterPair()) { 48 | return other.Overlaps(*this); 49 | } 50 | return false; 51 | } 52 | 53 | 54 | int X86ManagedRegister::AllocIdLow() const { 55 | const int r = RegId() - (kNumberOfCpuRegIds + kNumberOfXmmRegIds + 56 | kNumberOfX87RegIds); 57 | return kRegisterPairs[r].low; 58 | } 59 | 60 | 61 | int X86ManagedRegister::AllocIdHigh() const { 62 | const int r = RegId() - (kNumberOfCpuRegIds + kNumberOfXmmRegIds + 63 | kNumberOfX87RegIds); 64 | return kRegisterPairs[r].high; 65 | } 66 | 67 | 68 | } // namespace x86 69 | } // namespace whale 70 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/x86/registers_x86.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ASSEMBLER_X86_REGISTERS_X86_H_ 2 | #define WHALE_ASSEMBLER_X86_REGISTERS_X86_H_ 3 | 4 | #include 5 | 6 | namespace whale { 7 | namespace x86 { 8 | 9 | enum Register { 10 | EAX = 0, 11 | ECX = 1, 12 | EDX = 2, 13 | EBX = 3, 14 | ESP = 4, 15 | EBP = 5, 16 | ESI = 6, 17 | EDI = 7, 18 | kNumberOfCpuRegisters = 8, 19 | kFirstByteUnsafeRegister = 4, 20 | kNoRegister = -1 // Signals an illegal register. 21 | }; 22 | 23 | enum XmmRegister { 24 | XMM0 = 0, 25 | XMM1 = 1, 26 | XMM2 = 2, 27 | XMM3 = 3, 28 | XMM4 = 4, 29 | XMM5 = 5, 30 | XMM6 = 6, 31 | XMM7 = 7, 32 | kNumberOfXmmRegisters = 8, 33 | kNoXmmRegister = -1 // Signals an illegal register. 34 | }; 35 | 36 | } // namespace x86 37 | } // namespace whale 38 | 39 | #endif // WHALE_ASSEMBLER_X86_REGISTERS_X86_H_ 40 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/x86_64/managed_register_x86_64.cc: -------------------------------------------------------------------------------- 1 | #include "assembler/x86_64/managed_register_x86_64.h" 2 | 3 | namespace whale { 4 | namespace x86_64 { 5 | 6 | // Define register pairs. 7 | // This list must be kept in sync with the RegisterPair enum. 8 | #define REGISTER_PAIR_LIST(P) \ 9 | P(RAX, RDX) \ 10 | P(RAX, RCX) \ 11 | P(RAX, RBX) \ 12 | P(RAX, RDI) \ 13 | P(RDX, RCX) \ 14 | P(RDX, RBX) \ 15 | P(RDX, RDI) \ 16 | P(RCX, RBX) \ 17 | P(RCX, RDI) \ 18 | P(RBX, RDI) 19 | 20 | 21 | struct RegisterPairDescriptor { 22 | RegisterPair reg; // Used to verify that the enum is in sync. 23 | Register low; 24 | Register high; 25 | }; 26 | 27 | 28 | static const RegisterPairDescriptor kRegisterPairs[] = { 29 | #define REGISTER_PAIR_ENUMERATION(low, high) { low##_##high, low, high }, 30 | REGISTER_PAIR_LIST(REGISTER_PAIR_ENUMERATION) 31 | #undef REGISTER_PAIR_ENUMERATION 32 | }; 33 | 34 | 35 | bool X86_64ManagedRegister::Overlaps(const X86_64ManagedRegister &other) const { 36 | if (IsNoRegister() || other.IsNoRegister()) return false; 37 | if (Equals(other)) return true; 38 | if (IsRegisterPair()) { 39 | Register low = AsRegisterPairLow().AsRegister(); 40 | Register high = AsRegisterPairHigh().AsRegister(); 41 | return X86_64ManagedRegister::FromCpuRegister(low).Overlaps(other) || 42 | X86_64ManagedRegister::FromCpuRegister(high).Overlaps(other); 43 | } 44 | if (other.IsRegisterPair()) { 45 | return other.Overlaps(*this); 46 | } 47 | return false; 48 | } 49 | 50 | 51 | int X86_64ManagedRegister::AllocIdLow() const { 52 | const int r = RegId() - (kNumberOfCpuRegIds + kNumberOfXmmRegIds + 53 | kNumberOfX87RegIds); 54 | return kRegisterPairs[r].low; 55 | } 56 | 57 | 58 | int X86_64ManagedRegister::AllocIdHigh() const { 59 | const int r = RegId() - (kNumberOfCpuRegIds + kNumberOfXmmRegIds + 60 | kNumberOfX87RegIds); 61 | return kRegisterPairs[r].high; 62 | } 63 | 64 | 65 | } // namespace x86_64 66 | } // namespace whale 67 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/assembler/x86_64/registers_x86_64.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ASSEMBLER_REGISTERS_X86_64_H_ 2 | #define WHALE_ASSEMBLER_REGISTERS_X86_64_H_ 3 | 4 | namespace whale { 5 | namespace x86_64 { 6 | 7 | enum Register { 8 | RAX = 0, 9 | RCX = 1, 10 | RDX = 2, 11 | RBX = 3, 12 | RSP = 4, 13 | RBP = 5, 14 | RSI = 6, 15 | RDI = 7, 16 | R8 = 8, 17 | R9 = 9, 18 | R10 = 10, 19 | R11 = 11, 20 | R12 = 12, 21 | R13 = 13, 22 | R14 = 14, 23 | R15 = 15, 24 | kLastCpuRegister = 15, 25 | kNumberOfCpuRegisters = 16, 26 | kNoRegister = -1 // Signals an illegal register. 27 | }; 28 | 29 | enum FloatRegister { 30 | XMM0 = 0, 31 | XMM1 = 1, 32 | XMM2 = 2, 33 | XMM3 = 3, 34 | XMM4 = 4, 35 | XMM5 = 5, 36 | XMM6 = 6, 37 | XMM7 = 7, 38 | XMM8 = 8, 39 | XMM9 = 9, 40 | XMM10 = 10, 41 | XMM11 = 11, 42 | XMM12 = 12, 43 | XMM13 = 13, 44 | XMM14 = 14, 45 | XMM15 = 15, 46 | kNumberOfFloatRegisters = 16 47 | }; 48 | 49 | } // namespace x86_64 50 | } // namespace whale 51 | 52 | #endif // WHALE_ASSEMBLER_REGISTERS_X86_64_H_ 53 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/base/cxx_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_BASE_CXX_HELPER_H_ 2 | #define WHALE_BASE_CXX_HELPER_H_ 3 | 4 | #include 5 | #include "base/primitive_types.h" 6 | 7 | template 8 | U ForceCast(T *x) { 9 | return (U) (uintptr_t) x; 10 | } 11 | 12 | template 13 | U ForceCast(T &x) { 14 | return *(U *) &x; 15 | } 16 | 17 | template 18 | struct Identity { 19 | using type = T; 20 | }; 21 | 22 | template 23 | static inline R OffsetOf(uintptr_t ptr, size_t offset) { 24 | return reinterpret_cast(ptr + offset); 25 | } 26 | 27 | template 28 | static inline R OffsetOf(intptr_t ptr, size_t offset) { 29 | return reinterpret_cast(ptr + offset); 30 | } 31 | 32 | template 33 | static inline R OffsetOf(ptr_t ptr, size_t offset) { 34 | return (R) (reinterpret_cast(ptr) + offset); 35 | } 36 | 37 | template 38 | static inline T MemberOf(ptr_t ptr, size_t offset) { 39 | return *OffsetOf(ptr, offset); 40 | } 41 | 42 | static inline size_t DistanceOf(ptr_t a, ptr_t b) { 43 | return static_cast( 44 | abs(reinterpret_cast(b) - reinterpret_cast(a)) 45 | ); 46 | } 47 | 48 | template 49 | static inline void AssignOffset(ptr_t ptr, size_t offset, T member) { 50 | *OffsetOf(ptr, offset) = member; 51 | } 52 | 53 | #endif // WHALE_BASE_CXX_HELPER_H_ 54 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/base/enums.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_BASE_ENUMS_H_ 2 | #define WHALE_BASE_ENUMS_H_ 3 | 4 | 5 | #include 6 | #include 7 | 8 | enum class PointerSize : size_t { 9 | k32 = 4, 10 | k64 = 8 11 | }; 12 | 13 | inline std::ostream &operator<<(std::ostream &os, const PointerSize &rhs) { 14 | switch (rhs) { 15 | case PointerSize::k32: 16 | os << "k32"; 17 | break; 18 | case PointerSize::k64: 19 | os << "k64"; 20 | break; 21 | default: 22 | os << "PointerSize[" << static_cast(rhs) << "]"; 23 | break; 24 | } 25 | return os; 26 | } 27 | 28 | static constexpr PointerSize kRuntimePointerSize = sizeof(void *) == 8U 29 | ? PointerSize::k64 30 | : PointerSize::k32; 31 | 32 | #endif // WHALE_BASE_ENUMS_H_ 33 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/base/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_BASE_MACROS_H_ 2 | #define WHALE_BASE_MACROS_H_ 3 | 4 | #define DISALLOW_ALLOCATION() \ 5 | public: \ 6 | NO_RETURN ALWAYS_INLINE void operator delete(void*, size_t) { UNREACHABLE(); } \ 7 | ALWAYS_INLINE void* operator new(size_t, void* ptr) noexcept { return ptr; } \ 8 | ALWAYS_INLINE void operator delete(void*, void*) noexcept { } \ 9 | private: \ 10 | void* operator new(size_t) = delete // NOLINT 11 | 12 | #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ 13 | private: \ 14 | TypeName(); \ 15 | DISALLOW_COPY_AND_ASSIGN(TypeName) 16 | 17 | #define ALIGNED(x) __attribute__ ((__aligned__(x))) 18 | #define PACKED(x) __attribute__ ((__aligned__(x), __packed__)) 19 | 20 | #define OFFSETOF_MEMBER(t, f) offsetof(t, f) 21 | 22 | // Stringify the argument. 23 | #define QUOTE(x) #x 24 | #define STRINGIFY(x) QUOTE(x) 25 | 26 | #ifndef NDEBUG 27 | #define ALWAYS_INLINE 28 | #else 29 | #define ALWAYS_INLINE __attribute__ ((always_inline)) 30 | #endif 31 | 32 | // Define that a position within code is unreachable, for example: 33 | // int foo () { LOG(FATAL) << "Don't call me"; UNREACHABLE(); } 34 | // without the UNREACHABLE a return statement would be necessary. 35 | #define UNREACHABLE __builtin_unreachable 36 | 37 | #define LIKELY(x) __builtin_expect(!!(x), 1) 38 | #define UNLIKELY(x) __builtin_expect(!!(x), 0) 39 | 40 | #define NO_RETURN [[ noreturn ]] 41 | 42 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 43 | TypeName(const TypeName&); \ 44 | void operator=(const TypeName&) 45 | 46 | #define OPTION __unused 47 | 48 | #define OPEN_API __attribute__((visibility("default"))) 49 | #define C_API extern "C" 50 | 51 | #endif // WHALE_BASE_MACROS_H_ 52 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/base/offsets.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_BASE_OFFSETS_H_ 2 | #define WHALE_BASE_OFFSETS_H_ 3 | 4 | #include 5 | #include 6 | #include "base/enums.h" 7 | 8 | namespace whale { 9 | 10 | 11 | // Allow the meaning of offsets to be strongly typed. 12 | class Offset { 13 | public: 14 | constexpr explicit Offset(size_t val) : val_(val) {} 15 | 16 | constexpr int32_t Int32Value() const { 17 | return static_cast(val_); 18 | } 19 | 20 | constexpr uint32_t Uint32Value() const { 21 | return static_cast(val_); 22 | } 23 | 24 | constexpr size_t SizeValue() const { 25 | return val_; 26 | } 27 | 28 | protected: 29 | size_t val_; 30 | }; 31 | 32 | // Offsets relative to the current frame. 33 | class FrameOffset : public Offset { 34 | public: 35 | constexpr explicit FrameOffset(size_t val) : Offset(val) {} 36 | 37 | bool operator>(FrameOffset other) const { return val_ > other.val_; } 38 | 39 | bool operator<(FrameOffset other) const { return val_ < other.val_; } 40 | }; 41 | 42 | // Offsets relative to the current running thread. 43 | template 44 | class ThreadOffset : public Offset { 45 | public: 46 | constexpr explicit ThreadOffset(size_t val) : Offset(val) {} 47 | }; 48 | 49 | using ThreadOffset32 = ThreadOffset; 50 | using ThreadOffset64 = ThreadOffset; 51 | 52 | // Offsets relative to an object. 53 | class MemberOffset : public Offset { 54 | public: 55 | constexpr explicit MemberOffset(size_t val) : Offset(val) {} 56 | }; 57 | 58 | } 59 | 60 | #endif // WHALE_BASE_OFFSETS_H_ 61 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/base/primitive_types.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_BASE_PRIMITIVE_TYPES_H_ 2 | #define WHALE_BASE_PRIMITIVE_TYPES_H_ 3 | 4 | #include 5 | #include 6 | 7 | typedef uint8_t byte; 8 | typedef uint8_t u1; 9 | typedef uint16_t u2; 10 | typedef uint32_t u4; 11 | typedef uint64_t u8; 12 | 13 | 14 | typedef int8_t s1; 15 | typedef int16_t s2; 16 | typedef int32_t s4; 17 | typedef int64_t s8; 18 | 19 | typedef size_t offset_t; 20 | typedef void* ptr_t; 21 | 22 | #endif // WHALE_BASE_PRIMITIVE_TYPES_H_ 23 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/base/singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_BASE_SINGLETON_H_ 2 | #define WHALE_BASE_SINGLETON_H_ 3 | 4 | template 5 | class Singleton { 6 | public: 7 | Singleton(std::function init_function) : init_function_(init_function), 8 | initialized_(false) {} 9 | 10 | void Ensure() { 11 | if (!initialized_) { 12 | std::lock_guard guard(lock_); 13 | if (!initialized_) { 14 | init_function_(&instance_); 15 | initialized_ = true; 16 | } 17 | } 18 | } 19 | 20 | T Get() { 21 | Ensure(); 22 | return instance_; 23 | } 24 | 25 | private: 26 | typename std::conditional::value, bool, T>::type instance_; 27 | std::mutex lock_; 28 | std::function init_function_; 29 | bool initialized_; 30 | }; 31 | 32 | #endif // WHALE_BASE_SINGLETON_H_ 33 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/base/stringprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_BASE_STRINGPRINTF_H_ 2 | #define WHALE_BASE_STRINGPRINTF_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace whale { 8 | 9 | // Returns a string corresponding to printf-like formatting of the arguments. 10 | std::string StringPrintf(const char *fmt, ...) 11 | __attribute__((__format__(__printf__, 1, 2))); 12 | 13 | // Appends a printf-like formatting of the arguments to 'dst'. 14 | void StringAppendF(std::string *dst, const char *fmt, ...) 15 | __attribute__((__format__(__printf__, 2, 3))); 16 | 17 | // Appends a printf-like formatting of the arguments to 'dst'. 18 | void StringAppendV(std::string *dst, const char *format, va_list ap); 19 | 20 | } // namespace art 21 | 22 | #endif // WHALE_BASE_STRINGPRINTF_H_ 23 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm/decoder_arm.cc: -------------------------------------------------------------------------------- 1 | #include "dbi/arm/decoder_arm.h" 2 | 3 | #define CASE(mask, val, type) \ 4 | if ((((insn) & (mask)) == val)) { \ 5 | return type; \ 6 | } 7 | 8 | namespace whale { 9 | namespace arm { 10 | 11 | ArmInsnType DecodeArm(u4 insn) { 12 | CASE(0xe5f0000, 0x41f0000, kARM_LDR); 13 | CASE(0xfef0010, 0x8f0000, kARM_ADD); 14 | CASE(0xdef0000, 0x1a00000, kARM_MOV); 15 | CASE(0xf000000, 0xa000000, kARM_B); 16 | CASE(0xf000000, 0xb000000, kARM_BL); 17 | return kARM_UNHANDLED; 18 | } 19 | 20 | } // namespace arm 21 | } // namespace whale 22 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm/decoder_arm.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM_DECODER_ARM_H_ 2 | #define ARCH_ARM_DECODER_ARM_H_ 3 | 4 | #include "base/primitive_types.h" 5 | 6 | namespace whale { 7 | namespace arm { 8 | 9 | enum ArmInsnType { 10 | kARM_LDR, 11 | kARM_ADD, 12 | kARM_MOV, 13 | kARM_B, 14 | kARM_BL, 15 | kARM_VFP_VSTM_DP, 16 | kARM_VFP_VSTM_SP, 17 | kARM_VFP_VLDM_SP, 18 | kARM_VFP_VLDM_DP, 19 | kARM_VFP_VSTR_DP, 20 | kARM_VFP_VSTR_SP, 21 | kARM_VFP_VLDR_DP, 22 | kARM_VFP_VLDR_SP, 23 | 24 | kARM_UNHANDLED, 25 | }; 26 | 27 | ArmInsnType DecodeArm(u4 insn); 28 | 29 | } // namespace arm 30 | } // namespace whale 31 | 32 | #endif // ARCH_ARM_DECODER_ARM_H_ 33 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm/decoder_thumb.cc: -------------------------------------------------------------------------------- 1 | #include "dbi/arm/decoder_thumb.h" 2 | 3 | #define CASE(mask, val, type) \ 4 | if ((((insn) & (mask)) == val)) { \ 5 | return type; \ 6 | } 7 | 8 | namespace whale { 9 | namespace arm { 10 | 11 | 12 | ThumbInsnType DecodeThumb16(u2 insn) { 13 | CASE(0xf800, 0xa000, kTHUMB_ADD_FROM_PC16); 14 | CASE(0xff00, 0x4400, kTHUMB_ADDH16); 15 | CASE(0xf800, 0xe000, kTHUMB_B16); 16 | CASE(0xf000, 0xd000, kTHUMB_B_COND16); 17 | CASE(0xff87, 0x4780, kTHUMB_BLX16); 18 | CASE(0xff87, 0x4700, kTHUMB_BX16); 19 | CASE(0xfd00, 0xb900, kTHUMB_CBNZ16); 20 | CASE(0xfd00, 0xb100, kTHUMB_CBZ16); 21 | CASE(0xff00, 0x4500, kTHUMB_CMPH16); 22 | CASE(0xf800, 0x4800, kTHUMB_LDR_PC_16); 23 | CASE(0xff00, 0x4600, kTHUMB_MOVH16); 24 | return kTHUMB_UNHANDLED16; 25 | } 26 | 27 | ThumbInsnType DecodeThumb32(u4 insn) { 28 | CASE(0xf800d000, 0xf0009000, kTHUMB_B32); 29 | CASE(0xf800d000, 0xf000d000, kTHUMB_BL32); 30 | CASE(0xf800d000, 0xf000c000, kTHUMB_BL_ARM32); 31 | CASE(0xff7f0000, 0xf81f0000, kTHUMB_LDRBL32); 32 | CASE(0xff7f0000, 0xf83f0000, kTHUMB_LDRHL32); 33 | CASE(0xff7f0000, 0xf85f0000, kTHUMB_LDRL32); 34 | CASE(0xfff00fc0, 0xf9100000, kTHUMB_LDRSBL32); 35 | CASE(0xff7f0000, 0xf93f0000, kTHUMB_LDRSHL32); 36 | return kTHUMB_UNHANDLED32; 37 | } 38 | 39 | 40 | } // namespace arm 41 | } // namespace whale 42 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm/decoder_thumb.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM_DECODER_THUMB_H_ 2 | #define ARCH_ARM_DECODER_THUMB_H_ 3 | 4 | #include "base/primitive_types.h" 5 | 6 | namespace whale { 7 | namespace arm { 8 | 9 | enum ThumbInsnType { 10 | kTHUMB_ADD_FROM_PC16, 11 | kTHUMB_ADDH16, 12 | kTHUMB_B16, 13 | kTHUMB_B_COND16, 14 | kTHUMB_BLX16, 15 | kTHUMB_BX16, 16 | kTHUMB_CBNZ16, 17 | kTHUMB_CBZ16, 18 | kTHUMB_CMPH16, 19 | kTHUMB_LDR_PC_16, 20 | kTHUMB_MOVH16, 21 | kTHUMB_UNHANDLED16, 22 | 23 | kTHUMB_B32, 24 | kTHUMB_BL32, 25 | kTHUMB_BL_ARM32, 26 | kTHUMB_LDRBL32, 27 | kTHUMB_LDRHL32, 28 | kTHUMB_LDRL32, 29 | kTHUMB_LDRSBL32, 30 | kTHUMB_LDRSHL32, 31 | kTHUMB_UNHANDLED32 32 | }; 33 | 34 | ThumbInsnType DecodeThumb16(u2 insn); 35 | 36 | ThumbInsnType DecodeThumb32(u4 insn); 37 | 38 | /** 39 | * Bit[15:11] in Thumb32 : 40 | * 0b11101 41 | * 0b11110 42 | * 0b11111 43 | */ 44 | static inline bool Is32BitThumbInstruction(u2 insn) { 45 | return ((insn & 0xF000) == 0xF000) || ((insn & 0xF800) == 0xE800); 46 | } 47 | 48 | } // namespace arm 49 | } // namespace whale 50 | 51 | #endif // ARCH_ARM_DECODER_THUMB_H_ 52 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm/inline_hook_arm.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM_INLINEHOOK_ARM_H_ 2 | #define ARCH_ARM_INLINEHOOK_ARM_H_ 3 | 4 | #include "dbi/backup_code.h" 5 | #include "dbi/hook_common.h" 6 | #include "base/primitive_types.h" 7 | #include "base/align.h" 8 | 9 | namespace whale { 10 | namespace arm { 11 | 12 | class ArmInlineHook : public InlineHook { 13 | public: 14 | ArmInlineHook(intptr_t address, intptr_t replace, intptr_t *backup) 15 | : InlineHook(address, replace, backup) { 16 | is_thumb_ = static_cast(address & 0x1); 17 | if (is_thumb_) { 18 | address_ = RoundDown(address, 2); 19 | } 20 | } 21 | 22 | void StartHook() override; 23 | 24 | void StopHook() override; 25 | 26 | private: 27 | bool is_thumb_; 28 | BackupCode *backup_code_; 29 | void *trampoline_addr_; 30 | 31 | intptr_t BuildTrampoline(u4 tail); 32 | }; 33 | 34 | } // namespace arm 35 | } // namespace whale 36 | 37 | #endif // ARCH_ARM_INLINEHOOK_ARM_H_ 38 | 39 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm/registers_arm.h: -------------------------------------------------------------------------------- 1 | #ifndef ARM64_ARM_CONVENTION_H_ 2 | #define ARM64_ARM_CONVENTION_H_ 3 | 4 | #include 5 | #include "assembler/vixl/aarch32/operands-aarch32.h" 6 | 7 | namespace whale { 8 | namespace arm { 9 | 10 | 11 | enum ArmRegister { 12 | R0 = 0, 13 | R1 = 1, 14 | R2 = 2, 15 | R3 = 3, 16 | R4 = 4, 17 | R5 = 5, 18 | R6 = 6, 19 | R7 = 7, 20 | R8 = 8, 21 | R9 = 9, 22 | R10 = 10, 23 | R11 = 11, 24 | R12 = 12, 25 | R13 = 13, 26 | R14 = 14, 27 | R15 = 15, 28 | MR = 8, 29 | TR = 9, 30 | FP = 11, 31 | IP = 12, 32 | SP = 13, 33 | LR = 14, 34 | PC = 15, 35 | kNumberOfCoreRegisters = 16, 36 | kNoRegister = -1, 37 | }; 38 | 39 | const vixl::aarch32::Register &Reg(int reg) { 40 | #define CASE(x) case R##x: \ 41 | return vixl::aarch32::r##x; 42 | 43 | switch (reg) { 44 | CASE(0) 45 | CASE(1) 46 | CASE(2) 47 | CASE(3) 48 | CASE(4) 49 | CASE(5) 50 | CASE(6) 51 | CASE(7) 52 | CASE(8) 53 | CASE(9) 54 | CASE(10) 55 | CASE(11) 56 | CASE(12) 57 | CASE(13) 58 | CASE(14) 59 | CASE(15) 60 | default: 61 | LOG(FATAL) << "Unexpected register : " << reg; 62 | UNREACHABLE(); 63 | } 64 | #undef CASE 65 | } 66 | 67 | } // namespace arm 68 | } // namespace whale 69 | 70 | 71 | #endif // ARM64_ARM_CONVENTION_H_ 72 | 73 | 74 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm64/decoder_arm64.cc: -------------------------------------------------------------------------------- 1 | #include "dbi/arm64/decoder_arm64.h" 2 | #include "base/macros.h" 3 | 4 | #define CASE(mask, val, type) \ 5 | if ((((insn) & (mask)) == val)) { \ 6 | return type; \ 7 | } 8 | 9 | namespace whale { 10 | namespace arm64 { 11 | 12 | A64InsnType DecodeA64(u4 insn) { 13 | CASE(0x7e000000, 0x34000000, kA64_CBZ_CBNZ); 14 | CASE(0xff000010, 0x54000000, kA64_B_COND); 15 | CASE(0x7e000000, 0x36000000, kA64_TBZ_TBNZ); 16 | CASE(0x7c000000, 0x14000000, kA64_B_BL); 17 | CASE(0x3b000000, 0x18000000, kA64_LDR_LIT); 18 | CASE(0x1f000000, 0x10000000, kA64_ADR_ADRP); 19 | return kA64_UNHANDLED; 20 | } 21 | 22 | } // namespace arm64 23 | } // namespace whale 24 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm64/decoder_arm64.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM64_DECODER_H_ 2 | #define ARCH_ARM64_DECODER_H_ 3 | 4 | #include "base/primitive_types.h" 5 | 6 | namespace whale { 7 | namespace arm64 { 8 | 9 | enum A64InsnType { 10 | kA64_CBZ_CBNZ, 11 | kA64_B_COND, 12 | kA64_TBZ_TBNZ, 13 | kA64_B_BL, 14 | kA64_LDR_LIT, 15 | kA64_ADR_ADRP, 16 | kA64_UNHANDLED 17 | }; 18 | 19 | A64InsnType DecodeA64(u4 insn); 20 | 21 | } // namespace arm64 22 | } // namespace whale 23 | 24 | #endif // ARCH_ARM64_DECODER_H_ 25 | 26 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm64/inline_hook_arm64.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "platform/memory.h" 3 | #include "dbi/arm64/inline_hook_arm64.h" 4 | #include "dbi/arm64/registers_arm64.h" 5 | #include "dbi/arm64/instruction_rewriter_arm64.h" 6 | #include "assembler/vixl/aarch64/macro-assembler-aarch64.h" 7 | #include "base/align.h" 8 | #include "base/logging.h" 9 | 10 | #define __ masm. 11 | 12 | namespace whale { 13 | namespace arm64 { 14 | 15 | using namespace vixl::aarch64; // NOLINT 16 | 17 | 18 | void Arm64InlineHook::StartHook() { 19 | DCHECK(address_ != 0 && replace_ != 0); 20 | MacroAssembler masm; 21 | 22 | __ Mov(xTarget, GetReplaceAddress()); 23 | __ Br(xTarget); 24 | 25 | masm.FinalizeCode(); 26 | 27 | size_t backup_size = masm.GetSizeOfCodeGenerated(); 28 | backup_code_ = new BackupCode(GetTarget(), backup_size); 29 | 30 | if (backup_ != nullptr) { 31 | intptr_t tail = address_ + backup_size; 32 | intptr_t trampoline = BuildTrampoline(static_cast(tail)); 33 | *backup_ = trampoline; 34 | } 35 | 36 | ScopedMemoryPatch patch( 37 | GetTarget(), 38 | masm.GetBuffer()->GetStartAddress(), 39 | backup_size 40 | ); 41 | } 42 | 43 | intptr_t 44 | Arm64InlineHook::BuildTrampoline(u8 tail) { 45 | MacroAssembler masm; 46 | 47 | Arm64InstructionRewriter rewriter(&masm, backup_code_, GetTarget(), tail); 48 | rewriter.Rewrite(); 49 | 50 | __ Mov(xTarget, tail); 51 | __ Br(xTarget); 52 | 53 | masm.FinalizeCode(); 54 | 55 | size_t size = masm.GetBuffer()->GetSizeInBytes(); 56 | 57 | trampoline_addr_ = mmap(nullptr, GetPageSize(), PROT_READ | PROT_WRITE, 58 | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 59 | memcpy(trampoline_addr_, masm.GetBuffer()->GetStartAddress(), size); 60 | mprotect(trampoline_addr_, GetPageSize(), PROT_READ | PROT_EXEC); 61 | 62 | return reinterpret_cast(trampoline_addr_); 63 | } 64 | 65 | 66 | void Arm64InlineHook::StopHook() { 67 | size_t code_size = backup_code_->GetSizeInBytes(); 68 | void *insns = backup_code_->GetInstructions(); 69 | ScopedMemoryPatch patch(GetTarget(), insns, code_size); 70 | memcpy(GetTarget(), insns, code_size); 71 | if (trampoline_addr_ != nullptr) { 72 | munmap(trampoline_addr_, GetPageSize()); 73 | } 74 | } 75 | 76 | } // namespace arm64 77 | } // namespace whale 78 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm64/inline_hook_arm64.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_ARM64_INLINEHOOK_ARM64_H_ 2 | #define ARCH_ARM64_INLINEHOOK_ARM64_H_ 3 | 4 | #include "dbi/backup_code.h" 5 | #include "dbi/hook_common.h" 6 | #include "base/primitive_types.h" 7 | 8 | namespace whale { 9 | namespace arm64 { 10 | 11 | class Arm64InlineHook : public InlineHook { 12 | public: 13 | Arm64InlineHook(intptr_t address, intptr_t replace, intptr_t *backup) 14 | : InlineHook(address, replace, backup), backup_code_(nullptr), trampoline_addr_(nullptr) {} 15 | 16 | ~Arm64InlineHook() override { 17 | delete backup_code_; 18 | } 19 | 20 | void StartHook() override; 21 | 22 | void StopHook() override; 23 | 24 | private: 25 | BackupCode *backup_code_; 26 | void *trampoline_addr_; 27 | 28 | intptr_t BuildTrampoline(u8 tail); 29 | }; 30 | 31 | } // namespace arm64 32 | } // namespace whale 33 | 34 | #endif // ARCH_ARM64_INLINEHOOK_ARM64_H_ 35 | 36 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/arm64/instruction_rewriter_arm64.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_REWRITER_ARM64_H_ 2 | #define ARCH_REWRITER_ARM64_H_ 3 | 4 | #include "assembler/vixl/aarch64/macro-assembler-aarch64.h" 5 | #include "dbi/backup_code.h" 6 | #include "dbi/instruction_rewriter.h" 7 | #include "dbi/instruction_set.h" 8 | #include "base/primitive_types.h" 9 | #include "base/macros.h" 10 | 11 | namespace whale { 12 | namespace arm64 { 13 | 14 | class Arm64InstructionRewriter : public InstructionReWriter { 15 | public: 16 | Arm64InstructionRewriter(vixl::aarch64::MacroAssembler *masm, BackupCode *code, 17 | u8 origin_pc, u8 tail_pc) 18 | : masm_(masm), code_(code), cfg_pc_(origin_pc), tail_pc_(tail_pc) {} 19 | 20 | ~Arm64InstructionRewriter() = default; 21 | 22 | const InstructionSet GetISA() override { 23 | return InstructionSet::kArm64; 24 | } 25 | 26 | void Rewrite() override; 27 | 28 | ALWAYS_INLINE u4 *GetStartAddress() override { 29 | return masm_->GetBuffer()->GetStartAddress(); 30 | } 31 | 32 | ALWAYS_INLINE size_t GetCodeSize() override { 33 | return masm_->GetBuffer()->GetSizeInBytes(); 34 | } 35 | 36 | private: 37 | const u8 cfg_pc_; 38 | const u8 tail_pc_; 39 | vixl::aarch64::MacroAssembler *masm_; 40 | BackupCode *code_; 41 | 42 | ALWAYS_INLINE void EmitCode(u4 insn) { 43 | masm_->GetBuffer()->Emit32(insn); 44 | } 45 | 46 | void RewriteADR_ADRP(u8 pc, u4 insn); 47 | 48 | void RewriteB_BL(u8 pc, u4 insn); 49 | 50 | void RewriteCBZ_CBNZ(u8 pc, u4 insn); 51 | 52 | void RewriteB_COND(u8 pc, u4 insn); 53 | 54 | void RewriteTBZ_TBNZ(u8 pc, u4 insn); 55 | 56 | void RewriteLDR_LIT(u8 pc, u4 insn); 57 | }; 58 | 59 | 60 | } // namespace arm64 61 | } // namespace whale 62 | 63 | 64 | #endif // ARCH_REWRITER_ARM64_H_ 65 | 66 | 67 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/backup_code.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_BACKUP_CODE_H_ 2 | #define ARCH_BACKUP_CODE_H_ 3 | 4 | #include 5 | #include "base/primitive_types.h" 6 | #include "base/macros.h" 7 | #include "base/logging.h" 8 | 9 | 10 | namespace whale { 11 | 12 | class BackupCode { 13 | public: 14 | BackupCode(const void *address, const size_t size) : size_(size) { 15 | insns_ = malloc(size); 16 | memcpy(insns_, address, size); 17 | } 18 | 19 | ~BackupCode() { 20 | free(insns_); 21 | } 22 | 23 | size_t GetSizeInBytes() { 24 | return size_; 25 | } 26 | 27 | size_t GetCount(size_t insn_size) { 28 | return size_ / insn_size; 29 | } 30 | 31 | template 32 | size_t GetCount() { 33 | return GetCount(sizeof(T)); 34 | } 35 | 36 | template 37 | T *GetInstructions() { 38 | return reinterpret_cast(insns_); 39 | } 40 | 41 | intptr_t GetInstructions() { 42 | return reinterpret_cast(insns_); 43 | } 44 | 45 | private: 46 | void *insns_; 47 | size_t size_; 48 | 49 | private: 50 | DISALLOW_COPY_AND_ASSIGN(BackupCode); 51 | }; 52 | 53 | } // namespace whale 54 | 55 | #endif // ARCH_BACKUP_CODE_H_ 56 | 57 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/darwin/macho_import_hook.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_DBI_MACHO_IMPORT_HOOK_H_ 2 | #define WHALE_DBI_MACHO_IMPORT_HOOK_H_ 3 | 4 | #include "dbi/hook_common.h" 5 | #include 6 | #include 7 | #include 8 | #include "base/cxx_helper.h" 9 | #include "base/singleton.h" 10 | 11 | #ifndef S_LAZY_DYLIB_SYMBOL_POINTERS 12 | #define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 13 | #endif 14 | 15 | #if __LP64__ 16 | #define LC_SEGMENT_COMMAND LC_SEGMENT_64 17 | typedef mach_header_64 macho_header; 18 | typedef section_64 macho_section; 19 | typedef nlist_64 macho_nlist; 20 | typedef segment_command_64 macho_segment_command; 21 | #else 22 | #define LC_SEGMENT_COMMAND LC_SEGMENT 23 | typedef mach_header macho_header; 24 | typedef section macho_section; 25 | typedef nlist macho_nlist; 26 | typedef segment_command macho_segment_command; 27 | #endif 28 | 29 | namespace whale { 30 | namespace darwin { 31 | 32 | class MachoImportHook final : public ImportHook { 33 | public: 34 | MachoImportHook(const char *symbol_name, void *replace, void **backup) 35 | : ImportHook(symbol_name, replace, backup) {} 36 | 37 | void StartHook() override; 38 | 39 | void StopHook() override; 40 | 41 | void ImportHookOneMachO(const macho_header *mh, intptr_t slide); 42 | 43 | private: 44 | void **GetImportAddress(const macho_header *mh, intptr_t slide); 45 | }; 46 | 47 | } // namespace darwin 48 | } // namespace whale 49 | 50 | #endif // WHALE_DBI_MACHO_IMPORT_HOOK_H_ 51 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/hook_common.cc: -------------------------------------------------------------------------------- 1 | #include "dbi/hook_common.h" 2 | #include "hook_common.h" 3 | 4 | #if defined(linux) 5 | 6 | #include "platform/linux/process_map.h" 7 | 8 | #endif 9 | 10 | namespace whale { 11 | 12 | bool FindStdLibCallback(const char *path, bool *stop) { 13 | #if defined(linux) 14 | if (strstr(path, "system/") && strstr(path, "/libc.so")) { 15 | *stop = true; 16 | return true; 17 | } 18 | #elif defined(__APPLE__) 19 | if (strstr(path, "libc.dylib")) { 20 | *stop = true; 21 | return true; 22 | } 23 | #endif 24 | return false; 25 | } 26 | 27 | InterceptSysCallHook::InterceptSysCallHook(MemoryRangeCallback callback) 28 | : Hook() { 29 | if (callback == nullptr) { 30 | callback = FindStdLibCallback; 31 | } 32 | callback_ = callback; 33 | } 34 | 35 | void InterceptSysCallHook::StartHook() { 36 | bool stop_foreach = false; 37 | #if defined(linux) 38 | ForeachMemoryRange( 39 | [&](uintptr_t begin, uintptr_t end, char *perm, char *mapname) -> bool { 40 | if (strstr(perm, "x") && strstr(perm, "r")) { 41 | if (callback_(mapname, &stop_foreach)) { 42 | FindSysCalls(begin, end); 43 | } 44 | } 45 | return stop_foreach; 46 | }); 47 | #endif 48 | } 49 | 50 | void InterceptSysCallHook::StopHook() { 51 | 52 | } 53 | } // namespace whale 54 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/hook_common.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ARCH_HOOK_H_ 2 | #define WHALE_ARCH_HOOK_H_ 3 | 4 | #include 5 | #include 6 | #include "dbi/instruction_set.h" 7 | 8 | namespace whale { 9 | 10 | enum class HookType { 11 | kNone, 12 | kInlineHook, 13 | kImportHook, 14 | }; 15 | 16 | class Hook { 17 | public: 18 | int id_{}; 19 | 20 | virtual ~Hook() = default; 21 | 22 | virtual InstructionSet getISA() { 23 | return InstructionSet::kNone; 24 | } 25 | 26 | virtual HookType GetType() { 27 | return HookType::kNone; 28 | } 29 | 30 | virtual void StartHook() = 0; 31 | 32 | virtual void StopHook() = 0; 33 | }; 34 | 35 | class ImportHook : public Hook { 36 | public: 37 | ImportHook(const char *symbol_name, void *replace, void **backup) 38 | : symbol_name_(symbol_name), 39 | replace_(replace), 40 | backup_(backup) {} 41 | 42 | virtual ~ImportHook() override = default; 43 | 44 | HookType GetType() override { 45 | return HookType::kImportHook; 46 | } 47 | 48 | const char *GetSymbolName() { 49 | return symbol_name_; 50 | } 51 | 52 | template 53 | ALWAYS_INLINE T GetReplaceAddress() { 54 | return (T) replace_; 55 | } 56 | 57 | protected: 58 | const char *symbol_name_; 59 | std::map address_map_; 60 | void *replace_; 61 | void **backup_; 62 | }; 63 | 64 | class InlineHook : public Hook { 65 | public: 66 | InlineHook(intptr_t address, intptr_t replace, intptr_t *backup) 67 | : address_(address), 68 | replace_(replace), 69 | backup_(backup) {} 70 | 71 | virtual ~InlineHook() override = default; 72 | 73 | template 74 | ALWAYS_INLINE T GetTarget() { 75 | return (T) address_; 76 | } 77 | 78 | template 79 | ALWAYS_INLINE T GetReplaceAddress() { 80 | return (T) replace_; 81 | } 82 | 83 | HookType GetType() override { 84 | return HookType::kInlineHook; 85 | } 86 | 87 | protected: 88 | intptr_t address_; 89 | intptr_t replace_; 90 | intptr_t *backup_; 91 | }; 92 | 93 | typedef bool (*MemoryRangeCallback)(const char *path, bool *stop); 94 | 95 | class InterceptSysCallHook : public Hook { 96 | public: 97 | InterceptSysCallHook(MemoryRangeCallback callback); 98 | 99 | void StartHook(); 100 | 101 | void StopHook(); 102 | 103 | protected: 104 | virtual void FindSysCalls(uintptr_t start, uintptr_t end) = 0; 105 | 106 | MemoryRangeCallback callback_; 107 | }; 108 | 109 | } // namespace whale 110 | 111 | #endif // WHALE_ARCH_HOOK_H_ 112 | 113 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/instruction_rewriter.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_INSTRUCTION_REWRITER_H_ 2 | #define ARCH_INSTRUCTION_REWRITER_H_ 3 | 4 | #include "assembler/vixl/code-buffer-vixl.h" 5 | #include "dbi/instruction_set.h" 6 | 7 | namespace whale { 8 | 9 | using CodeBuffer = vixl::CodeBuffer; 10 | 11 | template 12 | class InstructionReWriter { 13 | 14 | virtual const InstructionSet GetISA() { 15 | return InstructionSet::kNone; 16 | } 17 | 18 | virtual InsnType *GetStartAddress() = 0; 19 | 20 | virtual size_t GetCodeSize() = 0; 21 | 22 | virtual void Rewrite() = 0; 23 | 24 | }; 25 | 26 | } // namespace whale 27 | 28 | #endif // ARCH_INSTRUCTION_REWRITER_H_ 29 | 30 | 31 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/instruction_set.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dbi/instruction_set.h" 4 | 5 | namespace whale { 6 | 7 | std::ostream &operator<<(std::ostream &os, const InstructionSet &rhs) { 8 | return os << GetInstructionSetString(rhs); 9 | } 10 | 11 | void InstructionSetAbort(InstructionSet isa) { 12 | switch (isa) { 13 | case InstructionSet::kArm: 14 | case InstructionSet::kThumb2: 15 | case InstructionSet::kArm64: 16 | case InstructionSet::kX86: 17 | case InstructionSet::kX86_64: 18 | case InstructionSet::kMips: 19 | case InstructionSet::kMips64: 20 | case InstructionSet::kNone: 21 | LOG(FATAL) << "Unsupported instruction set " << isa; 22 | UNREACHABLE(); 23 | } 24 | LOG(FATAL) << "Unknown ISA " << isa; 25 | UNREACHABLE(); 26 | } 27 | 28 | const char *GetInstructionSetString(InstructionSet isa) { 29 | switch (isa) { 30 | case InstructionSet::kArm: 31 | case InstructionSet::kThumb2: 32 | return "arm"; 33 | case InstructionSet::kArm64: 34 | return "arm64"; 35 | case InstructionSet::kX86: 36 | return "x86"; 37 | case InstructionSet::kX86_64: 38 | return "x86_64"; 39 | case InstructionSet::kMips: 40 | return "mips"; 41 | case InstructionSet::kMips64: 42 | return "mips64"; 43 | case InstructionSet::kNone: 44 | return "none"; 45 | } 46 | LOG(FATAL) << "Unknown ISA " << isa; 47 | UNREACHABLE(); 48 | } 49 | 50 | 51 | size_t GetInstructionSetAlignment(InstructionSet isa) { 52 | switch (isa) { 53 | case InstructionSet::kArm: 54 | // Fall-through. 55 | case InstructionSet::kThumb2: 56 | return kArmAlignment; 57 | case InstructionSet::kArm64: 58 | return kArm64Alignment; 59 | case InstructionSet::kX86: 60 | // Fall-through. 61 | case InstructionSet::kX86_64: 62 | return kX86Alignment; 63 | case InstructionSet::kMips: 64 | // Fall-through. 65 | case InstructionSet::kMips64: 66 | return kMipsAlignment; 67 | case InstructionSet::kNone: 68 | LOG(FATAL) << "ISA kNone does not have alignment."; 69 | UNREACHABLE(); 70 | } 71 | LOG(FATAL) << "Unknown ISA " << isa; 72 | UNREACHABLE(); 73 | } 74 | 75 | 76 | } // namespace whale 77 | 78 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | decoder.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2011 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef DECODER_H 25 | #define DECODER_H 26 | 27 | #include "config.h" 28 | 29 | typedef unsigned int _iflags; 30 | 31 | _DecodeResult decode_internal(_CodeInfo* ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); 32 | 33 | #endif /* DECODER_H */ 34 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/insts.h: -------------------------------------------------------------------------------- 1 | /* 2 | insts.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2018 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef INSTS_H 13 | #define INSTS_H 14 | 15 | #include "instructions.h" 16 | 17 | 18 | /* Flags Table */ 19 | extern _iflags FlagsTable[]; 20 | 21 | /* Root Trie DB */ 22 | extern _InstSharedInfo InstSharedInfoTable[]; 23 | extern _InstInfo InstInfos[]; 24 | extern _InstInfoEx InstInfosEx[]; 25 | extern _InstNode InstructionsTree[]; 26 | 27 | /* 3DNow! Trie DB */ 28 | extern _InstNode Table_0F_0F; 29 | /* AVX related: */ 30 | extern _InstNode Table_0F, Table_0F_38, Table_0F_3A; 31 | 32 | /* 33 | * The inst_lookup will return on of these two instructions according to the specified decoding mode. 34 | * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. 35 | */ 36 | extern _InstInfo II_MOVSXD; 37 | 38 | /* 39 | * The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction. 40 | * If 0x90 is prefixed by a usable REX it will become XCHG, otherwise it will become a NOP. 41 | * Also note that if it's prefixed by 0xf3, it becomes a Pause. 42 | */ 43 | extern _InstInfo II_NOP; 44 | extern _InstInfo II_PAUSE; 45 | 46 | /* 47 | * RDRAND and VMPTRLD share same 2.3 bytes opcode, and then alternates on the MOD bits, 48 | * RDRAND is OT_FULL_REG while VMPTRLD is OT_MEM, and there's no such mixed type. 49 | * So a hack into the inst_lookup was added for this decision, the DB isn't flexible enough. :( 50 | */ 51 | extern _InstInfo II_RDRAND; 52 | 53 | /* 54 | * Used for letting the extract operand know the type of operands without knowing the 55 | * instruction itself yet, because of the way those instructions work. 56 | * See function instructions.c!inst_lookup_3dnow. 57 | */ 58 | extern _InstInfo II_3DNOW; 59 | 60 | /* Helper tables for pseudo compare mnemonics. */ 61 | extern uint16_t CmpMnemonicOffsets[8]; /* SSE */ 62 | extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */ 63 | 64 | #endif /* INSTS_H */ 65 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/operands.h: -------------------------------------------------------------------------------- 1 | /* 2 | operands.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2018 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef OPERANDS_H 13 | #define OPERANDS_H 14 | 15 | #include "config.h" 16 | #include "decoder.h" 17 | #include "prefix.h" 18 | #include "instructions.h" 19 | 20 | 21 | extern uint32_t _REGISTERTORCLASS[]; 22 | 23 | int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, 24 | _iflags instFlags, _OpType type, _OperandNumberType opNum, 25 | unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, 26 | _DecodeType effAdrSz, int* lockableInstruction); 27 | 28 | #endif /* OPERANDS_H */ 29 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/prefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | prefix.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2018 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef PREFIX_H 13 | #define PREFIX_H 14 | 15 | #include "config.h" 16 | #include "decoder.h" 17 | 18 | 19 | /* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */ 20 | typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType; 21 | 22 | /* Specifies an index into a table of prefixes by their type. */ 23 | typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer; 24 | 25 | /* 26 | * This holds the prefixes state for the current instruction we decode. 27 | * decodedPrefixes includes all specific prefixes that the instruction got. 28 | * start is a pointer to the first prefix to take into account. 29 | * last is a pointer to the last byte we scanned. 30 | * Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. 31 | */ 32 | typedef struct { 33 | _iflags decodedPrefixes, usedPrefixes; 34 | const uint8_t *start, *last, *vexPos, *rexPos; 35 | _PrefixExtType prefixExtType; 36 | uint16_t unusedPrefixesMask; 37 | /* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */ 38 | int isOpSizeMandatory; 39 | /* If VEX prefix is used, store the VEX.vvvv field. */ 40 | unsigned int vexV; 41 | /* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */ 42 | unsigned int vrex; 43 | 44 | /* !! Make sure pfxIndexer is LAST! Otherwise memset won't work well with it. !! */ 45 | 46 | /* Holds the offset to the prefix byte by its type. */ 47 | int pfxIndexer[PFXIDX_MAX]; 48 | } _PrefixState; 49 | 50 | /* 51 | * Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). 52 | * REX is the fifth prefix type, this time I'm based on AMD64. 53 | * VEX is the 6th, though it can't be repeated. 54 | */ 55 | #define MAX_PREFIXES (5) 56 | 57 | int prefixes_is_valid(unsigned int ch, _DecodeType dt); 58 | void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi); 59 | void prefixes_ignore_all(_PrefixState* ps); 60 | uint16_t prefixes_set_unused_mask(_PrefixState* ps); 61 | void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt); 62 | void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di); 63 | 64 | #endif /* PREFIX_H */ 65 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/textdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | textdefs.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2018 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef TEXTDEFS_H 13 | #define TEXTDEFS_H 14 | 15 | #include "config.h" 16 | #include "wstring.h" 17 | 18 | #ifndef DISTORM_LIGHT 19 | 20 | #define PLUS_DISP_CHR '+' 21 | #define MINUS_DISP_CHR '-' 22 | #define OPEN_CHR '[' 23 | #define CLOSE_CHR ']' 24 | #define SP_CHR ' ' 25 | #define SEG_OFF_CHR ':' 26 | 27 | /* 28 | Naming Convention: 29 | 30 | * get - returns a pointer to a string. 31 | * str - concatenates to string. 32 | 33 | * hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. 34 | * code - means the function is used for disassembled instruction - Big Endian output. 35 | * off - means the function is used for 64bit offset - Big Endian output. 36 | 37 | * h - '0x' in front of the string. 38 | 39 | * b - byte 40 | * dw - double word (can be used for word also) 41 | * qw - quad word 42 | 43 | * all numbers are in HEX. 44 | */ 45 | 46 | void _FASTCALL_ str_hex_b(_WString* s, unsigned int x); 47 | void _FASTCALL_ str_code_hb(_WString* s, unsigned int x); 48 | void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x); 49 | void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]); 50 | 51 | #ifdef SUPPORT_64BIT_OFFSET 52 | void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x); 53 | #endif 54 | 55 | #endif /* DISTORM_LIGHT */ 56 | 57 | #endif /* TEXTDEFS_H */ 58 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/wstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2018 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #include "wstring.h" 13 | 14 | #ifndef DISTORM_LIGHT 15 | 16 | void strclear_WS(_WString* s) 17 | { 18 | s->p[0] = '\0'; 19 | s->length = 0; 20 | } 21 | 22 | void chrcat_WS(_WString* s, uint8_t ch) 23 | { 24 | s->p[s->length] = ch; 25 | s->p[s->length + 1] = '\0'; 26 | s->length += 1; 27 | } 28 | 29 | void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len) 30 | { 31 | s->length = len; 32 | memcpy((int8_t*)s->p, buf, len + 1); 33 | } 34 | 35 | void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len) 36 | { 37 | memcpy((int8_t*)&s->p[s->length], buf, len + 1); 38 | s->length += len; 39 | } 40 | 41 | void strcat_WS(_WString* s, const _WString* s2) 42 | { 43 | memcpy((int8_t*)&s->p[s->length], s2->p, s2->length + 1); 44 | s->length += s2->length; 45 | } 46 | 47 | #endif /* DISTORM_LIGHT */ 48 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/wstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2018 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef WSTRING_H 13 | #define WSTRING_H 14 | 15 | #include "config.h" 16 | 17 | #ifndef DISTORM_LIGHT 18 | 19 | void strclear_WS(_WString* s); 20 | void chrcat_WS(_WString* s, uint8_t ch); 21 | void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len); 22 | void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len); 23 | void strcat_WS(_WString* s, const _WString* s2); 24 | 25 | /* 26 | * Warning, this macro should be used only when the compiler knows the size of string in advance! 27 | * This macro is used in order to spare the call to strlen when the strings are known already. 28 | * Note: sizeof includes NULL terminated character. 29 | */ 30 | #define strcat_WSN(s, t) strcatlen_WS((s), ((const int8_t*)t), sizeof((t))-1) 31 | #define strcpy_WSN(s, t) strcpylen_WS((s), ((const int8_t*)t), sizeof((t))-1) 32 | 33 | #endif /* DISTORM_LIGHT */ 34 | 35 | #endif /* WSTRING_H */ 36 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/distorm/x86defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | x86defs.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2018 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef X86DEFS_H 13 | #define X86DEFS_H 14 | 15 | 16 | #define SEG_REGS_MAX (6) 17 | #define CREGS_MAX (9) 18 | #define DREGS_MAX (8) 19 | 20 | /* Maximum instruction size, including prefixes */ 21 | #define INST_MAXIMUM_SIZE (15) 22 | 23 | /* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */ 24 | #define INST_CMP_MAX_RANGE (8) 25 | 26 | /* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */ 27 | #define INST_VCMP_MAX_RANGE (32) 28 | 29 | /* Wait instruction byte code. */ 30 | #define INST_WAIT_INDEX (0x9b) 31 | 32 | /* Lea instruction byte code. */ 33 | #define INST_LEA_INDEX (0x8d) 34 | 35 | /* NOP/XCHG instruction byte code. */ 36 | #define INST_NOP_INDEX (0x90) 37 | 38 | /* ARPL/MOVSXD instruction byte code. */ 39 | #define INST_ARPL_INDEX (0x63) 40 | 41 | /* 42 | * Minimal MODR/M value of divided instructions. 43 | * It's 0xc0, two MSBs set, which indicates a general purpose register is used too. 44 | */ 45 | #define INST_DIVIDED_MODRM (0xc0) 46 | 47 | /* This is the escape byte value used for 3DNow! instructions. */ 48 | #define _3DNOW_ESCAPE_BYTE (0x0f) 49 | 50 | #define PREFIX_LOCK (0xf0) 51 | #define PREFIX_REPNZ (0xf2) 52 | #define PREFIX_REP (0xf3) 53 | #define PREFIX_CS (0x2e) 54 | #define PREFIX_SS (0x36) 55 | #define PREFIX_DS (0x3e) 56 | #define PREFIX_ES (0x26) 57 | #define PREFIX_FS (0x64) 58 | #define PREFIX_GS (0x65) 59 | #define PREFIX_OP_SIZE (0x66) 60 | #define PREFIX_ADDR_SIZE (0x67) 61 | #define PREFIX_VEX2b (0xc5) 62 | #define PREFIX_VEX3b (0xc4) 63 | 64 | /* REX prefix value range, 64 bits mode decoding only. */ 65 | #define PREFIX_REX_LOW (0x40) 66 | #define PREFIX_REX_HI (0x4f) 67 | /* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */ 68 | #define EX_GPR_BASE (8) 69 | 70 | /* Mask for REX and VEX features: */ 71 | /* Base */ 72 | #define PREFIX_EX_B (1) 73 | /* Index */ 74 | #define PREFIX_EX_X (2) 75 | /* Register */ 76 | #define PREFIX_EX_R (4) 77 | /* Operand Width */ 78 | #define PREFIX_EX_W (8) 79 | /* Vector Lengh */ 80 | #define PREFIX_EX_L (0x10) 81 | 82 | #endif /* X86DEFS_H */ 83 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/inline_hook_x86.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dbi/x86/inline_hook_x86.h" 4 | #include "dbi/x86/instruction_rewriter_x86.h" 5 | #include "assembler/x86/assembler_x86.h" 6 | #include "platform/memory.h" 7 | 8 | #define __ masm. 9 | 10 | namespace whale { 11 | namespace x86 { 12 | 13 | void X86InlineHook::StartHook() { 14 | 15 | DCHECK(address_ != 0 && replace_ != 0); 16 | X86Assembler masm; 17 | __ movl(EDX, Immediate(replace_)); 18 | __ jmp(EDX); 19 | masm.FinalizeCode(); 20 | 21 | size_t backup_size = masm.GetBuffer()->Size(); 22 | size_t code_aligned_size = 0; 23 | do { 24 | u1 *code = reinterpret_cast(address_) + code_aligned_size; 25 | u1 size = Decode(code, UINT8_MAX, 0).size; 26 | code_aligned_size += size; 27 | } while (code_aligned_size < backup_size); 28 | 29 | backup_size = code_aligned_size; 30 | 31 | backup_code_ = new BackupCode(GetTarget(), backup_size); 32 | 33 | if (backup_ != nullptr) { 34 | intptr_t tail = address_ + backup_size; 35 | intptr_t trampoline = BuildTrampoline(static_cast(tail)); 36 | *backup_ = trampoline; 37 | } 38 | 39 | ScopedMemoryPatch patch(GetTarget(), masm.GetBuffer()->contents(), 40 | masm.GetBuffer()->Size()); 41 | } 42 | 43 | intptr_t X86InlineHook::BuildTrampoline(u4 tail) { 44 | X86Assembler masm; 45 | X86InstructionRewriter rewriter(&masm, backup_code_, GetTarget(), tail); 46 | rewriter.Rewrite(); 47 | 48 | __ movl(EDX, Immediate(tail)); 49 | __ jmp(EDX); 50 | masm.FinalizeCode(); 51 | size_t size = masm.GetBuffer()->Size(); 52 | 53 | trampoline_addr_ = mmap(nullptr, GetPageSize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 54 | memcpy(trampoline_addr_, masm.GetBuffer()->contents(), size); 55 | mprotect(trampoline_addr_, GetPageSize(), PROT_READ | PROT_EXEC); 56 | return reinterpret_cast(trampoline_addr_); 57 | } 58 | 59 | 60 | void X86InlineHook::StopHook() { 61 | size_t code_size = backup_code_->GetSizeInBytes(); 62 | void *insns = backup_code_->GetInstructions(); 63 | ScopedMemoryPatch patch(GetTarget(), insns, code_size); 64 | memcpy(GetTarget(), insns, code_size); 65 | if (trampoline_addr_ != nullptr) { 66 | munmap(trampoline_addr_, GetPageSize()); 67 | } 68 | } 69 | 70 | } // namespace x86 71 | } // namespace whale 72 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/inline_hook_x86.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ARCH_X86_INLINE_HOOK_X86_H_ 2 | #define WHALE_ARCH_X86_INLINE_HOOK_X86_H_ 3 | 4 | #include "dbi/hook_common.h" 5 | #include "base/primitive_types.h" 6 | #include "dbi/backup_code.h" 7 | 8 | namespace whale { 9 | namespace x86 { 10 | 11 | class X86InlineHook : public InlineHook { 12 | public: 13 | X86InlineHook(intptr_t address, intptr_t replace, intptr_t *backup) 14 | : InlineHook(address, replace, backup), backup_code_(nullptr), 15 | trampoline_addr_(nullptr) {} 16 | 17 | ~X86InlineHook() override { 18 | delete backup_code_; 19 | } 20 | 21 | void StartHook() override; 22 | 23 | void StopHook() override; 24 | 25 | private: 26 | BackupCode *backup_code_; 27 | void *trampoline_addr_; 28 | 29 | intptr_t BuildTrampoline(u4 tail); 30 | }; 31 | 32 | } // namespace x86 33 | } // namespace whale 34 | 35 | #endif // WHALE_ARCH_X86_INLINE_HOOK_X86_H_ 36 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/instruction_rewriter_x86.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_X86_REWRITER_X86_H_ 2 | #define ARCH_X86_REWRITER_X86_H_ 3 | 4 | #include 5 | #include "assembler/x86/assembler_x86.h" 6 | #include "base/primitive_types.h" 7 | #include "dbi/backup_code.h" 8 | #include "dbi/instruction_rewriter.h" 9 | #include "dbi/instruction_set.h" 10 | #include "base/macros.h" 11 | 12 | namespace whale { 13 | namespace x86 { 14 | 15 | class X86InstructionRewriter : public InstructionReWriter { 16 | public: 17 | X86InstructionRewriter(whale::x86::X86Assembler *masm, BackupCode *code, 18 | u4 origin_pc, u4 tail_pc) 19 | : masm_(masm), code_(code), cfg_pc_(origin_pc), tail_pc_(tail_pc) {} 20 | 21 | ~X86InstructionRewriter() = default; 22 | 23 | const InstructionSet GetISA() override { 24 | return InstructionSet::kX86; 25 | } 26 | 27 | void Rewrite() override; 28 | 29 | u1 *GetStartAddress() override { 30 | return masm_->GetBuffer()->contents(); 31 | } 32 | 33 | size_t GetCodeSize() override { 34 | return masm_->GetBuffer()->Size(); 35 | } 36 | 37 | void EmitCode(u1 *start, size_t size) { 38 | for (int i = 0; i < size; ++i) { 39 | AssemblerBuffer::EnsureCapacity ensured(masm_->GetBuffer()); 40 | masm_->GetBuffer()->Emit(start[i]); 41 | } 42 | } 43 | 44 | private: 45 | const u4 cfg_pc_; 46 | const u4 tail_pc_; 47 | whale::x86::X86Assembler *masm_; 48 | BackupCode *code_; 49 | 50 | void Rewrite_Call(u1 *current, u4 pc, _DInst insn); 51 | 52 | bool IsGetPCThunkToRegister(u4 address, Register *reg); 53 | 54 | void Rewrite_Jmp(u1 *current, u4 pc, _DInst insn); 55 | 56 | void Rewrite_JRCXZ(u1 *current, u4 pc, _DInst insn); 57 | }; 58 | 59 | 60 | } // namespace arm64 61 | } // namespace whale 62 | 63 | 64 | #endif // ARCH_X86_REWRITER_X86_H_ 65 | 66 | 67 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/intercept_syscall_x86.cc: -------------------------------------------------------------------------------- 1 | #include "dbi/x86/intercept_syscall_x86.h" 2 | #include "base/primitive_types.h" 3 | 4 | namespace whale { 5 | namespace x86 { 6 | 7 | 8 | void X86InterceptSysCallHook::FindSysCalls(uintptr_t start_addr, uintptr_t end_addr) { 9 | u1 *start = reinterpret_cast(start_addr); 10 | u1 *end = reinterpret_cast(end_addr) - 1; 11 | while (start < end) { 12 | // int 80h 13 | if (*start == 0xcd & *(++start) == 0x80) { 14 | // eax: sysnum 15 | // ebx: arg0 16 | // ecx: arg1 17 | // edx: arg2 18 | // esi: arg3 19 | // edi: arg4 20 | // ebp: arg5 21 | } 22 | } 23 | 24 | } 25 | 26 | 27 | } // namespace x86 28 | } // namespace whale 29 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86/intercept_syscall_x86.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_DBI_X86_INTERCEPT_SYSCALL_HOOK_H_ 2 | #define WHALE_DBI_X86_INTERCEPT_SYSCALL_HOOK_H_ 3 | 4 | #include "dbi/hook_common.h" 5 | 6 | namespace whale { 7 | namespace x86 { 8 | 9 | class X86InterceptSysCallHook : public InterceptSysCallHook { 10 | public: 11 | X86InterceptSysCallHook(MemoryRangeCallback callback) : InterceptSysCallHook(callback) {} 12 | 13 | protected: 14 | void FindSysCalls(uintptr_t start, uintptr_t end); 15 | }; 16 | 17 | } // namespace x86 18 | } // namespace whale 19 | 20 | #endif // WHALE_DBI_X86_INTERCEPT_SYSCALL_HOOK_H_ 21 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86_64/inline_hook_x86_64.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "assembler/x86_64/assembler_x86_64.h" 5 | #include "dbi/x86_64/inline_hook_x86_64.h" 6 | #include "dbi/x86_64/instruction_rewriter_x86_64.h" 7 | #include "dbi/x86/distorm/distorm.h" 8 | 9 | #define __ masm. 10 | 11 | namespace whale { 12 | namespace x86_64 { 13 | 14 | 15 | void X86_64InlineHook::StartHook() { 16 | CHECK(address_ != 0 && replace_ != 0); 17 | X86_64Assembler masm; 18 | 19 | __ movq(RAX, Immediate(replace_)); 20 | __ jmp(RAX); 21 | masm.FinalizeCode(); 22 | 23 | size_t backup_size = masm.GetBuffer()->Size(); 24 | size_t code_aligned_size = 0; 25 | do { 26 | u1 *code = reinterpret_cast(address_) + code_aligned_size; 27 | u1 size = Decode(code, UINT8_MAX, 1).size; 28 | code_aligned_size += size; 29 | } while (code_aligned_size < backup_size); 30 | 31 | backup_size = code_aligned_size; 32 | backup_code_ = new BackupCode(GetTarget(), backup_size); 33 | 34 | if (backup_ != nullptr) { 35 | intptr_t tail = address_ + backup_size; 36 | intptr_t trampoline = BuildTrampoline(static_cast(tail)); 37 | *backup_ = trampoline; 38 | } 39 | 40 | ScopedMemoryPatch patch(GetTarget(), masm.GetBuffer()->contents(), 41 | masm.GetBuffer()->Size()); 42 | } 43 | 44 | intptr_t X86_64InlineHook::BuildTrampoline(u8 tail) { 45 | X86_64Assembler masm; 46 | X86_64InstructionRewriter rewriter(&masm, backup_code_, GetTarget(), tail); 47 | rewriter.Rewrite(); 48 | 49 | __ movq(R12, Immediate(tail)); 50 | __ jmp(R12); 51 | 52 | masm.FinalizeCode(); 53 | 54 | size_t size = masm.GetBuffer()->Size(); 55 | trampoline_addr_ = mmap(nullptr, GetPageSize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 56 | memcpy(trampoline_addr_, masm.GetBuffer()->contents(), size); 57 | mprotect(trampoline_addr_, GetPageSize(), PROT_READ | PROT_EXEC); 58 | return reinterpret_cast(trampoline_addr_); 59 | } 60 | 61 | 62 | void X86_64InlineHook::StopHook() { 63 | size_t code_size = backup_code_->GetSizeInBytes(); 64 | void *insns = backup_code_->GetInstructions(); 65 | ScopedMemoryPatch patch(GetTarget(), insns, code_size); 66 | memcpy(GetTarget(), insns, code_size); 67 | if (trampoline_addr_ != nullptr) { 68 | munmap(trampoline_addr_, GetPageSize()); 69 | } 70 | } 71 | 72 | } // namespace x86 73 | } // namespace whale 74 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86_64/inline_hook_x86_64.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_ARCH_X86_64_INLINE_HOOK_X86_64_H_ 2 | #define WHALE_ARCH_X86_64_INLINE_HOOK_X86_64_H_ 3 | 4 | #include "dbi/hook_common.h" 5 | #include "base/primitive_types.h" 6 | #include "dbi/backup_code.h" 7 | 8 | namespace whale { 9 | namespace x86_64 { 10 | 11 | class X86_64InlineHook : public InlineHook { 12 | public: 13 | X86_64InlineHook(intptr_t address, intptr_t replace, intptr_t *backup) 14 | : InlineHook(address, replace, backup), backup_code_(nullptr), 15 | trampoline_addr_(nullptr) {} 16 | 17 | ~X86_64InlineHook() override { 18 | delete backup_code_; 19 | } 20 | 21 | void StartHook() override; 22 | 23 | void StopHook() override; 24 | 25 | private: 26 | BackupCode *backup_code_; 27 | void *trampoline_addr_; 28 | 29 | intptr_t BuildTrampoline(u8 tail); 30 | }; 31 | 32 | } // namespace x86 33 | } // namespace whale 34 | 35 | #endif // WHALE_ARCH_X86_64_INLINE_HOOK_X86_64_H_ 36 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/dbi/x86_64/instruction_rewriter_x86_64.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_X86_64_REWRITER_X86_64_H_ 2 | #define ARCH_X86_64_REWRITER_X86_64_H_ 3 | 4 | #include 5 | #include "assembler/x86_64/assembler_x86_64.h" 6 | #include "base/primitive_types.h" 7 | #include "dbi/backup_code.h" 8 | #include "dbi/instruction_rewriter.h" 9 | #include "dbi/instruction_set.h" 10 | #include "base/macros.h" 11 | 12 | namespace whale { 13 | namespace x86_64 { 14 | 15 | class X86_64InstructionRewriter : public InstructionReWriter { 16 | public: 17 | X86_64InstructionRewriter(X86_64Assembler *masm, BackupCode *code, 18 | u8 origin_pc, u8 tail_pc) 19 | : masm_(masm), code_(code), cfg_pc_(origin_pc), tail_pc_(tail_pc) {} 20 | 21 | ~X86_64InstructionRewriter() = default; 22 | 23 | const InstructionSet GetISA() override { 24 | return InstructionSet::kX86_64; 25 | } 26 | 27 | void Rewrite() override; 28 | 29 | u1 *GetStartAddress() override { 30 | return masm_->GetBuffer()->contents(); 31 | } 32 | 33 | size_t GetCodeSize() override { 34 | return masm_->GetBuffer()->Size(); 35 | } 36 | 37 | void EmitCode(u1 *start, size_t size) { 38 | for (int i = 0; i < size; ++i) { 39 | AssemblerBuffer::EnsureCapacity ensured(masm_->GetBuffer()); 40 | masm_->GetBuffer()->Emit(start[i]); 41 | } 42 | } 43 | 44 | private: 45 | const u8 cfg_pc_; 46 | const u8 tail_pc_; 47 | X86_64Assembler *masm_; 48 | BackupCode *code_; 49 | 50 | void Rewrite_Mov(u1 *current, u8 pc, _DInst insn); 51 | 52 | void Rewrite_Call(u1 *current, u8 pc, _DInst insn); 53 | 54 | void Rewrite_Jmp(u1 *current, u8 pc, _DInst insn); 55 | 56 | void Rewrite_JRCXZ(u1 *current, u8 pc, _DInst insn); 57 | }; 58 | 59 | 60 | } // namespace arm64 61 | } // namespace whale 62 | 63 | 64 | #endif // ARCH_X86_64_REWRITER_X86_64_H_ 65 | 66 | 67 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/interceptor.cc: -------------------------------------------------------------------------------- 1 | #include "interceptor.h" 2 | 3 | namespace whale { 4 | 5 | Interceptor *Interceptor::Instance() { 6 | static Interceptor instance; 7 | return &instance; 8 | } 9 | 10 | void Interceptor::AddHook(std::unique_ptr &hook) { 11 | hook->id_ = static_cast(hook_list_.size()); 12 | hook->StartHook(); 13 | hook_list_.push_back(std::move(hook)); 14 | } 15 | 16 | void Interceptor::RemoveHook(int id) { 17 | for (auto &entry : hook_list_) { 18 | if (entry->id_ == id) { 19 | hook_list_.remove(entry); 20 | entry->StopHook(); 21 | break; 22 | } 23 | } 24 | } 25 | 26 | void Interceptor::TraverseHooks(std::function &)> visitor) { 27 | for (auto &hook : hook_list_) { 28 | visitor(hook); 29 | } 30 | } 31 | 32 | } // namespace whale 33 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/interceptor.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_CODE_INTERCEPTOR_H_ 2 | #define WHALE_CODE_INTERCEPTOR_H_ 3 | 4 | #include 5 | #include 6 | #include "base/logging.h" 7 | #include "dbi/instruction_set.h" 8 | #include "dbi/hook_common.h" 9 | 10 | namespace whale { 11 | 12 | class Interceptor { 13 | public: 14 | static Interceptor *Instance(); 15 | 16 | void AddHook(std::unique_ptr &hook); 17 | 18 | void RemoveHook(int id); 19 | 20 | void RemoveHook(std::unique_ptr &hook) { 21 | RemoveHook(hook->id_); 22 | } 23 | void TraverseHooks(std::function&)> visitor); 24 | 25 | private: 26 | std::list> hook_list_; 27 | }; 28 | 29 | } // namespace whale 30 | 31 | #endif // WHALE_CODE_INTERCEPTOR_H_ 32 | 33 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/aarch64/internal.h: -------------------------------------------------------------------------------- 1 | #if defined(__aarch64__) || defined(__arm64__) 2 | 3 | /* 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | ``Software''), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22 | 23 | #define AARCH64_RET_VOID 0 24 | #define AARCH64_RET_INT64 1 25 | #define AARCH64_RET_INT128 2 26 | 27 | #define AARCH64_RET_UNUSED3 3 28 | #define AARCH64_RET_UNUSED4 4 29 | #define AARCH64_RET_UNUSED5 5 30 | #define AARCH64_RET_UNUSED6 6 31 | #define AARCH64_RET_UNUSED7 7 32 | 33 | /* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4, 34 | so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */ 35 | #define AARCH64_RET_S4 8 36 | #define AARCH64_RET_S3 9 37 | #define AARCH64_RET_S2 10 38 | #define AARCH64_RET_S1 11 39 | 40 | #define AARCH64_RET_D4 12 41 | #define AARCH64_RET_D3 13 42 | #define AARCH64_RET_D2 14 43 | #define AARCH64_RET_D1 15 44 | 45 | #define AARCH64_RET_Q4 16 46 | #define AARCH64_RET_Q3 17 47 | #define AARCH64_RET_Q2 18 48 | #define AARCH64_RET_Q1 19 49 | 50 | /* Note that each of the sub-64-bit integers gets two entries. */ 51 | #define AARCH64_RET_UINT8 20 52 | #define AARCH64_RET_UINT16 22 53 | #define AARCH64_RET_UINT32 24 54 | 55 | #define AARCH64_RET_SINT8 26 56 | #define AARCH64_RET_SINT16 28 57 | #define AARCH64_RET_SINT32 30 58 | 59 | #define AARCH64_RET_MASK 31 60 | 61 | #define AARCH64_RET_IN_MEM (1 << 5) 62 | #define AARCH64_RET_NEED_COPY (1 << 6) 63 | 64 | #define AARCH64_FLAG_ARG_V_BIT 7 65 | #define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT) 66 | 67 | #define N_X_ARG_REG 8 68 | #define N_V_ARG_REG 8 69 | #define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8) 70 | 71 | 72 | #endif -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/arm/internal.h: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | #define ARM_TYPE_VFP_S 0 4 | #define ARM_TYPE_VFP_D 1 5 | #define ARM_TYPE_VFP_N 2 6 | #define ARM_TYPE_INT64 3 7 | #define ARM_TYPE_INT 4 8 | #define ARM_TYPE_VOID 5 9 | #define ARM_TYPE_STRUCT 6 10 | 11 | 12 | #endif -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/debug.c: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | debug.c - Copyright (c) 1996 Red Hat, Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | ``Software''), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | DEALINGS IN THE SOFTWARE. 23 | ----------------------------------------------------------------------- */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | /* General debugging routines */ 31 | 32 | void ffi_stop_here(void) 33 | { 34 | /* This function is only useful for debugging purposes. 35 | Place a breakpoint on ffi_stop_here to be notified of 36 | significant events. */ 37 | } 38 | 39 | /* This function should only be called via the FFI_ASSERT() macro */ 40 | 41 | void ffi_assert(char *expr, char *file, int line) 42 | { 43 | fprintf(stderr, "ASSERTION FAILURE: %s at %s:%d\n", expr, file, line); 44 | ffi_stop_here(); 45 | abort(); 46 | } 47 | 48 | /* Perform a sanity check on an ffi_type structure */ 49 | 50 | void ffi_type_test(ffi_type *a, char *file, int line) 51 | { 52 | FFI_ASSERT_AT(a != NULL, file, line); 53 | 54 | FFI_ASSERT_AT(a->type <= FFI_TYPE_LAST, file, line); 55 | FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->size > 0, file, line); 56 | FFI_ASSERT_AT(a->type == FFI_TYPE_VOID || a->alignment > 0, file, line); 57 | FFI_ASSERT_AT((a->type != FFI_TYPE_STRUCT && a->type != FFI_TYPE_COMPLEX) 58 | || a->elements != NULL, file, line); 59 | FFI_ASSERT_AT(a->type != FFI_TYPE_COMPLEX 60 | || (a->elements != NULL 61 | && a->elements[0] != NULL && a->elements[1] == NULL), 62 | file, line); 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/ffi.h: -------------------------------------------------------------------------------- 1 | #ifdef __aarch64__ 2 | 3 | #include 4 | 5 | 6 | #endif 7 | #ifdef __i386__ 8 | 9 | #include 10 | 11 | 12 | #endif 13 | #ifdef __arm__ 14 | 15 | #include 16 | 17 | 18 | #endif 19 | #ifdef __x86_64__ 20 | 21 | #include 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/ffi_cfi.h: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc. 3 | 4 | Conditionally assemble cfi directives. Only necessary for building libffi. 5 | ----------------------------------------------------------------------- */ 6 | 7 | #ifndef FFI_CFI_H 8 | #define FFI_CFI_H 9 | 10 | #ifdef HAVE_AS_CFI_PSEUDO_OP 11 | 12 | # define cfi_startproc .cfi_startproc 13 | # define cfi_endproc .cfi_endproc 14 | # define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off 15 | # define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg 16 | # define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off 17 | # define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off 18 | # define cfi_offset(reg, off) .cfi_offset reg, off 19 | # define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off 20 | # define cfi_register(r1, r2) .cfi_register r1, r2 21 | # define cfi_return_column(reg) .cfi_return_column reg 22 | # define cfi_restore(reg) .cfi_restore reg 23 | # define cfi_same_value(reg) .cfi_same_value reg 24 | # define cfi_undefined(reg) .cfi_undefined reg 25 | # define cfi_remember_state .cfi_remember_state 26 | # define cfi_restore_state .cfi_restore_state 27 | # define cfi_window_save .cfi_window_save 28 | # define cfi_personality(enc, exp) .cfi_personality enc, exp 29 | # define cfi_lsda(enc, exp) .cfi_lsda enc, exp 30 | # define cfi_escape(...) .cfi_escape __VA_ARGS__ 31 | 32 | #else 33 | 34 | # define cfi_startproc 35 | # define cfi_endproc 36 | # define cfi_def_cfa(reg, off) 37 | # define cfi_def_cfa_register(reg) 38 | # define cfi_def_cfa_offset(off) 39 | # define cfi_adjust_cfa_offset(off) 40 | # define cfi_offset(reg, off) 41 | # define cfi_rel_offset(reg, off) 42 | # define cfi_register(r1, r2) 43 | # define cfi_return_column(reg) 44 | # define cfi_restore(reg) 45 | # define cfi_same_value(reg) 46 | # define cfi_undefined(reg) 47 | # define cfi_remember_state 48 | # define cfi_restore_state 49 | # define cfi_window_save 50 | # define cfi_personality(enc, exp) 51 | # define cfi_lsda(enc, exp) 52 | # define cfi_escape(...) 53 | 54 | #endif /* HAVE_AS_CFI_PSEUDO_OP */ 55 | #endif /* FFI_CFI_H */ 56 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/ffi_cxx.cc: -------------------------------------------------------------------------------- 1 | #include "ffi_cxx.h" 2 | 3 | FFICallInterface::~FFICallInterface() { 4 | for (FFIClosure *closure : closures_) { 5 | delete closure; 6 | } 7 | delete cif_; 8 | delete types_; 9 | } 10 | 11 | 12 | void FFIDispatcher(ffi_cif *cif OPTION, void *ret, void **args, void *userdata) { 13 | FFIClosure *closure = reinterpret_cast(userdata); 14 | FFICallback callback = closure->GetCallback(); 15 | callback(closure, ret, args, closure->GetUserData()); 16 | } 17 | 18 | 19 | FFIClosure *FFICallInterface::CreateClosure(void *userdata, FFICallback callback) { 20 | std::lock_guard guard(lock_); 21 | FFIClosure *closure = new FFIClosure(this, userdata, callback); 22 | ffi_prep_closure_loc(closure->closure_, cif_, FFIDispatcher, closure, closure->code_); 23 | closures_.push_back(closure); 24 | return closure; 25 | } 26 | 27 | static ffi_type *FFIGetCType(FFIType type) { 28 | switch (type) { 29 | case FFIType::kFFITypeVoid: 30 | return &ffi_type_void; 31 | case FFIType::kFFITypeU1: 32 | return &ffi_type_uint8; 33 | case FFIType::kFFITypeU2: 34 | return &ffi_type_uint16; 35 | case FFIType::kFFITypeU4: 36 | return &ffi_type_uint32; 37 | case FFIType::kFFITypeU8: 38 | return &ffi_type_uint64; 39 | case FFIType::kFFITypeS1: 40 | return &ffi_type_sint8; 41 | case FFIType::kFFITypeS2: 42 | return &ffi_type_sint16; 43 | case FFIType::kFFITypeS4: 44 | return &ffi_type_sint32; 45 | case FFIType::kFFITypeS8: 46 | return &ffi_type_sint64; 47 | case FFIType::kFFITypePointer: 48 | return &ffi_type_pointer; 49 | case FFIType::kFFITypeFloat: 50 | return &ffi_type_float; 51 | case FFIType::kFFITypeDouble: 52 | return &ffi_type_double; 53 | } 54 | } 55 | 56 | FFICallInterface *FFICallInterface::FinalizeCif() { 57 | cif_ = new ffi_cif; 58 | types_ = new ffi_type *[parameters_.size()]; 59 | int idx = 0; 60 | for (FFIType type : parameters_) { 61 | types_[idx] = FFIGetCType(type); 62 | idx++; 63 | } 64 | ffi_prep_cif(cif_, FFI_DEFAULT_ABI, 65 | (unsigned int) parameters_.size(), FFIGetCType(return_type_), types_); 66 | return this; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/ffi_cxx.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_FFI_CXX_H_ 2 | #define WHALE_FFI_CXX_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "ffi.h" 8 | #include "base/macros.h" 9 | 10 | enum class FFIType { 11 | kFFITypeVoid, 12 | kFFITypeU1, 13 | kFFITypeU2, 14 | kFFITypeU4, 15 | kFFITypeU8, 16 | kFFITypeS1, 17 | kFFITypeS2, 18 | kFFITypeS4, 19 | kFFITypeS8, 20 | kFFITypePointer, 21 | kFFITypeFloat, 22 | kFFITypeDouble, 23 | }; 24 | 25 | class FFICallInterface; 26 | 27 | class FFIClosure; 28 | 29 | typedef void (*FFICallback)(FFIClosure *closure, void *ret, void **args, void *userdata); 30 | 31 | class FFIClosure { 32 | public: 33 | FFIClosure(FFICallInterface *cif, void *userdata, FFICallback callback) : cif_(cif), 34 | userdata_(userdata), 35 | callback_(callback) { 36 | closure_ = reinterpret_cast(ffi_closure_alloc(sizeof(ffi_closure), &code_)); 37 | } 38 | 39 | ~FFIClosure() { 40 | ffi_closure_free(closure_); 41 | } 42 | 43 | void *GetCode() { 44 | return code_; 45 | } 46 | 47 | void *GetUserData() { 48 | return userdata_; 49 | } 50 | 51 | FFICallInterface *GetCif() { 52 | return cif_; 53 | } 54 | 55 | FFICallback GetCallback() { 56 | return callback_; 57 | } 58 | 59 | private: 60 | friend class FFICallInterface; 61 | 62 | FFICallInterface *cif_; 63 | ffi_closure *closure_; 64 | FFICallback callback_; 65 | void *code_; 66 | void *userdata_; 67 | 68 | }; 69 | 70 | class FFICallInterface { 71 | public: 72 | FFICallInterface(const FFIType return_type) : return_type_(return_type) {} 73 | 74 | ~FFICallInterface(); 75 | 76 | FFICallInterface *Parameter(const FFIType parameter) { 77 | parameters_.push_back(parameter); 78 | return this; 79 | } 80 | 81 | FFICallInterface *Parameters(unsigned int count, ...) { 82 | va_list ap; 83 | va_start(ap, count); 84 | while (count-- > 0) { 85 | Parameter(va_arg(ap, FFIType)); 86 | } 87 | va_end(ap); 88 | return this; 89 | } 90 | 91 | FFICallInterface *FinalizeCif(); 92 | 93 | size_t GetParameterCount() { 94 | return parameters_.size(); 95 | } 96 | 97 | std::list GetParameters() { 98 | return parameters_; 99 | } 100 | 101 | FFIClosure *CreateClosure(void *userdata, FFICallback callback); 102 | 103 | void RemoveClosure(FFIClosure *closure) { 104 | std::lock_guard guard(lock_); 105 | closures_.remove(closure); 106 | } 107 | 108 | private: 109 | std::mutex lock_; 110 | ffi_cif *cif_; 111 | ffi_type **types_; 112 | std::list parameters_; 113 | const FFIType return_type_; 114 | std::list closures_; 115 | }; 116 | 117 | #endif //WHALE_FFI_CXX_H_ 118 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/fficonfig.h: -------------------------------------------------------------------------------- 1 | #if defined(__aarch64__) || defined(__arm64__) 2 | #include 3 | 4 | 5 | #endif 6 | #ifdef __i386__ 7 | 8 | #include 9 | 10 | 11 | #endif 12 | #ifdef __arm__ 13 | 14 | #include 15 | 16 | 17 | #endif 18 | #ifdef __x86_64__ 19 | 20 | #include 21 | #endif 22 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/ffitarget.h: -------------------------------------------------------------------------------- 1 | #ifdef __aarch64__ 2 | 3 | #include 4 | 5 | 6 | #endif 7 | #ifdef __i386__ 8 | 9 | #include 10 | 11 | 12 | #endif 13 | #ifdef __arm__ 14 | 15 | #include 16 | 17 | 18 | #endif 19 | #ifdef __x86_64__ 20 | 21 | #include 22 | 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/platform_include/ffitarget_arm64.h: -------------------------------------------------------------------------------- 1 | #ifdef __aarch64__ 2 | 3 | /* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | ``Software''), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23 | 24 | #ifndef LIBFFI_TARGET_H 25 | #define LIBFFI_TARGET_H 26 | 27 | #ifndef LIBFFI_H 28 | #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." 29 | #endif 30 | 31 | #ifndef LIBFFI_ASM 32 | #ifdef __ILP32__ 33 | #define FFI_SIZEOF_ARG 8 34 | #define FFI_SIZEOF_JAVA_RAW 4 35 | typedef unsigned long long ffi_arg; 36 | typedef signed long long ffi_sarg; 37 | #else 38 | typedef unsigned long ffi_arg; 39 | typedef signed long ffi_sarg; 40 | #endif 41 | 42 | typedef enum ffi_abi 43 | { 44 | FFI_FIRST_ABI = 0, 45 | FFI_SYSV, 46 | FFI_LAST_ABI, 47 | FFI_DEFAULT_ABI = FFI_SYSV 48 | } ffi_abi; 49 | #endif 50 | 51 | /* ---- Definitions for closures ----------------------------------------- */ 52 | 53 | #define FFI_CLOSURES 1 54 | #define FFI_NATIVE_RAW_API 0 55 | 56 | #if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE 57 | 58 | #ifdef __MACH__ 59 | #define FFI_TRAMPOLINE_SIZE 16 60 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET 16 61 | #else 62 | #error "No trampoline table implementation" 63 | #endif 64 | 65 | #else 66 | #define FFI_TRAMPOLINE_SIZE 24 67 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE 68 | #endif 69 | 70 | /* ---- Internal ---- */ 71 | 72 | #if defined (__APPLE__) 73 | #define FFI_TARGET_SPECIFIC_VARIADIC 74 | #define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs 75 | #else 76 | /* iOS reserves x18 for the system. Disable Go closures until 77 | a new static chain is chosen. */ 78 | #define FFI_GO_CLOSURES 1 79 | #endif 80 | 81 | #define FFI_TARGET_HAS_COMPLEX_TYPE 82 | 83 | #endif 84 | 85 | 86 | #endif -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/platform_include/ffitarget_armv7.h: -------------------------------------------------------------------------------- 1 | #ifdef __arm__ 2 | 3 | /* -----------------------------------------------------------------*-C-*- 4 | ffitarget.h - Copyright (c) 2012 Anthony Green 5 | Copyright (c) 2010 CodeSourcery 6 | Copyright (c) 1996-2003 Red Hat, Inc. 7 | 8 | Target configuration macros for ARM. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining 11 | a copy of this software and associated documentation files (the 12 | ``Software''), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included 19 | in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | 30 | ----------------------------------------------------------------------- */ 31 | 32 | #ifndef LIBFFI_TARGET_H 33 | #define LIBFFI_TARGET_H 34 | 35 | #ifndef LIBFFI_H 36 | #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." 37 | #endif 38 | 39 | #ifndef LIBFFI_ASM 40 | typedef unsigned long ffi_arg; 41 | typedef signed long ffi_sarg; 42 | 43 | typedef enum ffi_abi { 44 | FFI_FIRST_ABI = 0, 45 | FFI_SYSV, 46 | FFI_VFP, 47 | FFI_LAST_ABI, 48 | #ifdef __ARM_PCS_VFP 49 | FFI_DEFAULT_ABI = FFI_VFP, 50 | #else 51 | FFI_DEFAULT_ABI = FFI_SYSV, 52 | #endif 53 | } ffi_abi; 54 | #endif 55 | 56 | #define FFI_EXTRA_CIF_FIELDS \ 57 | int vfp_used; \ 58 | unsigned short vfp_reg_free, vfp_nargs; \ 59 | signed char vfp_args[16] \ 60 | 61 | #define FFI_TARGET_SPECIFIC_VARIADIC 62 | #define FFI_TARGET_HAS_COMPLEX_TYPE 63 | 64 | /* ---- Definitions for closures ----------------------------------------- */ 65 | 66 | #define FFI_CLOSURES 1 67 | #define FFI_GO_CLOSURES 1 68 | #define FFI_NATIVE_RAW_API 0 69 | 70 | #if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE 71 | 72 | #ifdef __MACH__ 73 | #define FFI_TRAMPOLINE_SIZE 12 74 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET 8 75 | #else 76 | #error "No trampoline table implementation" 77 | #endif 78 | 79 | #else 80 | #define FFI_TRAMPOLINE_SIZE 12 81 | #define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE 82 | #endif 83 | 84 | #endif 85 | 86 | 87 | #endif -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/x86/asmnames.h: -------------------------------------------------------------------------------- 1 | #ifdef __x86_64__ 2 | 3 | #ifndef ASMNAMES_H 4 | #define ASMNAMES_H 5 | 6 | #define C2(X, Y) X ## Y 7 | #define C1(X, Y) C2(X, Y) 8 | #ifdef __USER_LABEL_PREFIX__ 9 | # define C(X) C1(__USER_LABEL_PREFIX__, X) 10 | #else 11 | # define C(X) X 12 | #endif 13 | 14 | #ifdef __APPLE__ 15 | # define L(X) C1(L, X) 16 | #else 17 | # define L(X) C1(.L, X) 18 | #endif 19 | 20 | #if defined(__ELF__) && defined(__PIC__) 21 | # define PLT(X) X@PLT 22 | #else 23 | # define PLT(X) X 24 | #endif 25 | 26 | #ifdef __ELF__ 27 | # define ENDF(X) .type X,@function; .size X, . - X 28 | #else 29 | # define ENDF(X) 30 | #endif 31 | 32 | #endif /* ASMNAMES_H */ 33 | 34 | 35 | #endif -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/x86/internal.h: -------------------------------------------------------------------------------- 1 | #ifdef __i386__ 2 | 3 | #define X86_RET_FLOAT 0 4 | #define X86_RET_DOUBLE 1 5 | #define X86_RET_LDOUBLE 2 6 | #define X86_RET_SINT8 3 7 | #define X86_RET_SINT16 4 8 | #define X86_RET_UINT8 5 9 | #define X86_RET_UINT16 6 10 | #define X86_RET_INT64 7 11 | #define X86_RET_INT32 8 12 | #define X86_RET_VOID 9 13 | #define X86_RET_STRUCTPOP 10 14 | #define X86_RET_STRUCTARG 11 15 | #define X86_RET_STRUCT_1B 12 16 | #define X86_RET_STRUCT_2B 13 17 | #define X86_RET_UNUSED14 14 18 | #define X86_RET_UNUSED15 15 19 | 20 | #define X86_RET_TYPE_MASK 15 21 | #define X86_RET_POP_SHIFT 4 22 | 23 | #define R_EAX 0 24 | #define R_EDX 1 25 | #define R_ECX 2 26 | 27 | #ifdef __PCC__ 28 | # define HAVE_FASTCALL 0 29 | #else 30 | # define HAVE_FASTCALL 1 31 | #endif 32 | 33 | 34 | #endif -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/libffi/x86/internal64.h: -------------------------------------------------------------------------------- 1 | #ifdef __x86_64__ 2 | 3 | #define UNIX64_RET_VOID 0 4 | #define UNIX64_RET_UINT8 1 5 | #define UNIX64_RET_UINT16 2 6 | #define UNIX64_RET_UINT32 3 7 | #define UNIX64_RET_SINT8 4 8 | #define UNIX64_RET_SINT16 5 9 | #define UNIX64_RET_SINT32 6 10 | #define UNIX64_RET_INT64 7 11 | #define UNIX64_RET_XMM32 8 12 | #define UNIX64_RET_XMM64 9 13 | #define UNIX64_RET_X87 10 14 | #define UNIX64_RET_X87_2 11 15 | #define UNIX64_RET_ST_XMM0_RAX 12 16 | #define UNIX64_RET_ST_RAX_XMM0 13 17 | #define UNIX64_RET_ST_XMM0_XMM1 14 18 | #define UNIX64_RET_ST_RAX_RDX 15 19 | 20 | #define UNIX64_RET_LAST 15 21 | 22 | #define UNIX64_FLAG_RET_IN_MEM (1 << 10) 23 | #define UNIX64_FLAG_XMM_ARGS (1 << 11) 24 | #define UNIX64_SIZE_SHIFT 12 25 | 26 | 27 | #endif -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/platform/linux/process_map.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "platform/linux/process_map.h" 5 | #include "process_map.h" 6 | 7 | 8 | namespace whale { 9 | 10 | std::unique_ptr FindFileMemoryRange(const char *name) { 11 | std::unique_ptr range(new MemoryRange); 12 | range->base_ = UINTPTR_MAX; 13 | ForeachMemoryRange( 14 | [&](uintptr_t begin, uintptr_t end, char *perm, char *mapname) -> bool { 15 | if (strstr(mapname, name)) { 16 | if (range->path_ == nullptr) { 17 | range->path_ = strdup(mapname); 18 | } 19 | if (range->base_ > begin) { 20 | range->base_ = begin; 21 | } 22 | if (range->end_ < end) { 23 | range->end_ = end; 24 | } 25 | } 26 | return true; 27 | }); 28 | return range; 29 | } 30 | 31 | std::unique_ptr FindExecuteMemoryRange(const char *name) { 32 | std::unique_ptr range(new MemoryRange); 33 | ForeachMemoryRange( 34 | [&](uintptr_t begin, uintptr_t end, char *perm, char *mapname) -> bool { 35 | if (strncmp(mapname, "/system/fake-libs/", 18) == 0) { 36 | return true; 37 | } 38 | if (strstr(mapname, name) && strstr(perm, "x") && strstr(perm, "r")) { 39 | range->path_ = strdup(mapname); 40 | range->base_ = begin; 41 | range->end_ = end; 42 | return false; 43 | } 44 | return true; 45 | }); 46 | return range; 47 | } 48 | 49 | void 50 | ForeachMemoryRange(std::function callback) { 51 | FILE *f; 52 | if ((f = fopen("/proc/self/maps", "r"))) { 53 | char buf[PATH_MAX], perm[12] = {'\0'}, dev[12] = {'\0'}, mapname[PATH_MAX] = {'\0'}; 54 | uintptr_t begin, end, inode, foo; 55 | 56 | while (!feof(f)) { 57 | if (fgets(buf, sizeof(buf), f) == 0) 58 | break; 59 | sscanf(buf, "%lx-%lx %s %lx %s %ld %s", &begin, &end, perm, 60 | &foo, dev, &inode, mapname); 61 | if (!callback(begin, end, perm, mapname)) { 62 | break; 63 | } 64 | } 65 | fclose(f); 66 | } 67 | } 68 | 69 | bool IsFileInMemory(const char *name) { 70 | bool found = false; 71 | ForeachMemoryRange( 72 | [&](uintptr_t begin, uintptr_t end, char *perm, char *mapname) -> bool { 73 | if (strstr(mapname, name)) { 74 | found = true; 75 | return false; 76 | } 77 | return true; 78 | }); 79 | return found; 80 | } 81 | 82 | } // namespace whale 83 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/platform/linux/process_map.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_PLATFORM_PROCESS_MAP_H_ 2 | #define WHALE_PLATFORM_PROCESS_MAP_H_ 3 | 4 | #include 5 | #include 6 | #include "base/primitive_types.h" 7 | 8 | namespace whale { 9 | 10 | struct MemoryRange { 11 | public: 12 | MemoryRange() : base_(0), end_(0), path_(nullptr) {} 13 | 14 | ~MemoryRange() { 15 | if (path_ != nullptr) { 16 | free((void *) path_); 17 | path_ = nullptr; 18 | } 19 | } 20 | 21 | bool IsValid() { 22 | return path_ != nullptr && base_ < end_; 23 | } 24 | 25 | bool IsInRange(uintptr_t address) { 26 | return IsValid() && base_ <= address && end_ >= address; 27 | } 28 | 29 | const char *path_; 30 | uintptr_t base_; 31 | uintptr_t end_; 32 | }; 33 | 34 | bool IsFileInMemory(const char *name); 35 | 36 | std::unique_ptr FindExecuteMemoryRange(const char *name); 37 | 38 | std::unique_ptr FindFileMemoryRange(const char *name); 39 | 40 | void ForeachMemoryRange(std::function callback); 41 | 42 | } // namespace whale 43 | 44 | #endif // WHALE_PLATFORM_PROCESS_MAP_H_ 45 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/platform/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef PLATFORM_SCOPED_MEMORY_ACCESS_H_ 2 | #define PLATFORM_SCOPED_MEMORY_ACCESS_H_ 3 | 4 | #include 5 | 6 | namespace whale { 7 | 8 | class ScopedMemoryPatch { 9 | public: 10 | ScopedMemoryPatch(void *address, void *patch, size_t size); 11 | 12 | ~ScopedMemoryPatch(); 13 | 14 | private: 15 | void *address_; 16 | void *patch_; 17 | size_t size_; 18 | }; 19 | 20 | } // namespace whale 21 | 22 | #endif // PLATFORM_SCOPED_MEMORY_ACCESS_H_ 23 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/simulator/code_simulator.cc: -------------------------------------------------------------------------------- 1 | #include "simulator/code_simulator.h" 2 | #include "simulator/code_simulator_arm64.h" 3 | 4 | namespace whale { 5 | 6 | CodeSimulator *CodeSimulator::CreateCodeSimulator(InstructionSet target_isa) { 7 | switch (target_isa) { 8 | case InstructionSet::kArm64: 9 | return arm64::CodeSimulatorArm64::CreateCodeSimulatorArm64(); 10 | default: 11 | return nullptr; 12 | } 13 | } 14 | 15 | CodeSimulator *CreateCodeSimulator(InstructionSet target_isa) { 16 | return CodeSimulator::CreateCodeSimulator(target_isa); 17 | } 18 | 19 | } // namespace whale 20 | 21 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/simulator/code_simulator.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_SIMULATOR_CODE_SIMULATOR_H_ 2 | #define WHALE_SIMULATOR_CODE_SIMULATOR_H_ 3 | 4 | #include 5 | #include "dbi/instruction_set.h" 6 | #include "base/primitive_types.h" 7 | 8 | namespace whale { 9 | 10 | class CodeSimulator { 11 | public: 12 | CodeSimulator() = default; 13 | 14 | virtual ~CodeSimulator() = default; 15 | 16 | // Returns a null pointer if a simulator cannot be found for target_isa. 17 | static CodeSimulator *CreateCodeSimulator(InstructionSet target_isa); 18 | 19 | virtual void RunFrom(intptr_t code_buffer) = 0; 20 | 21 | // Get return value according to C ABI. 22 | virtual bool GetCReturnBool() const = 0; 23 | 24 | virtual s4 GetCReturnInt32() const = 0; 25 | 26 | virtual s8 GetCReturnInt64() const = 0; 27 | 28 | private: 29 | DISALLOW_COPY_AND_ASSIGN(CodeSimulator); 30 | }; 31 | 32 | } // namespace whale 33 | 34 | #endif // WHALE_SIMULATOR_CODE_SIMULATOR_H_ 35 | 36 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/simulator/code_simulator_arm64.cc: -------------------------------------------------------------------------------- 1 | #include "vixl/aarch64/instructions-aarch64.h" 2 | #include "simulator/code_simulator_arm64.h" 3 | #include "base/logging.h" 4 | 5 | namespace whale { 6 | namespace arm64 { 7 | 8 | using namespace vixl::aarch64; // NOLINT(build/namespaces) 9 | 10 | CodeSimulatorArm64* CodeSimulatorArm64::CreateCodeSimulatorArm64() { 11 | if (kCanSimulate) { 12 | return new CodeSimulatorArm64(); 13 | } else { 14 | return nullptr; 15 | } 16 | } 17 | 18 | CodeSimulatorArm64::CodeSimulatorArm64() 19 | : CodeSimulator(), decoder_(nullptr), simulator_(nullptr) { 20 | CHECK(kCanSimulate); 21 | decoder_ = new Decoder(); 22 | simulator_ = new Simulator(decoder_); 23 | } 24 | 25 | CodeSimulatorArm64::~CodeSimulatorArm64() { 26 | CHECK(kCanSimulate); 27 | delete simulator_; 28 | delete decoder_; 29 | } 30 | 31 | void CodeSimulatorArm64::RunFrom(intptr_t code_buffer) { 32 | CHECK(kCanSimulate); 33 | simulator_->RunFrom(reinterpret_cast(code_buffer)); 34 | } 35 | 36 | bool CodeSimulatorArm64::GetCReturnBool() const { 37 | CHECK(kCanSimulate); 38 | return static_cast(simulator_->ReadWRegister(0)); 39 | } 40 | 41 | int32_t CodeSimulatorArm64::GetCReturnInt32() const { 42 | CHECK(kCanSimulate); 43 | return simulator_->ReadWRegister(0); 44 | } 45 | 46 | int64_t CodeSimulatorArm64::GetCReturnInt64() const { 47 | CHECK(kCanSimulate); 48 | return simulator_->ReadXRegister(0); 49 | } 50 | 51 | 52 | } // namespace arm64 53 | } // namespace whale 54 | 55 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/simulator/code_simulator_arm64.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_SIMULATOR_CODE_SIMULATOR_ARM64_H_ 2 | #define WHALE_SIMULATOR_CODE_SIMULATOR_ARM64_H_ 3 | 4 | #include 5 | #include "dbi/instruction_set.h" 6 | #include "base/primitive_types.h" 7 | #include "vixl/aarch64/decoder-aarch64.h" 8 | #include "vixl/aarch64/simulator-aarch64.h" 9 | #include "simulator/code_simulator.h" 10 | 11 | namespace whale { 12 | namespace arm64 { 13 | 14 | class CodeSimulatorArm64 : public CodeSimulator { 15 | public: 16 | static CodeSimulatorArm64 *CreateCodeSimulatorArm64(); 17 | 18 | ~CodeSimulatorArm64() override; 19 | 20 | void RunFrom(intptr_t code_buffer) override; 21 | 22 | bool GetCReturnBool() const override; 23 | 24 | int32_t GetCReturnInt32() const override; 25 | 26 | int64_t GetCReturnInt64() const override; 27 | 28 | private: 29 | CodeSimulatorArm64(); 30 | 31 | vixl::aarch64::Decoder *decoder_; 32 | vixl::aarch64::Simulator *simulator_; 33 | 34 | static constexpr bool kCanSimulate = (kRuntimeISA != InstructionSet::kArm64); 35 | 36 | DISALLOW_COPY_AND_ASSIGN(CodeSimulatorArm64); 37 | }; 38 | 39 | } 40 | } // namespace whale 41 | 42 | #endif // WHALE_SIMULATOR_CODE_SIMULATOR_ARM64_H_ 43 | 44 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/simulator/code_simulator_container.cc: -------------------------------------------------------------------------------- 1 | #include "simulator/code_simulator_container.h" 2 | #include "simulator/code_simulator.h" 3 | 4 | namespace whale { 5 | 6 | 7 | CodeSimulatorContainer::CodeSimulatorContainer(InstructionSet target_isa) : simulator_(nullptr) { 8 | simulator_ = CodeSimulator::CreateCodeSimulator(target_isa); 9 | } 10 | 11 | 12 | CodeSimulatorContainer::~CodeSimulatorContainer() { 13 | delete simulator_; 14 | } 15 | 16 | 17 | } -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/src/simulator/code_simulator_container.h: -------------------------------------------------------------------------------- 1 | #ifndef WHALE_SIMULATOR_CODE_SIMULATOR_CONTAINER_H_ 2 | #define WHALE_SIMULATOR_CODE_SIMULATOR_CONTAINER_H_ 3 | 4 | #include 5 | #include "simulator/code_simulator.h" 6 | #include "base/logging.h" 7 | 8 | namespace whale { 9 | 10 | 11 | class CodeSimulatorContainer { 12 | public: 13 | explicit CodeSimulatorContainer(InstructionSet target_isa); 14 | 15 | ~CodeSimulatorContainer(); 16 | 17 | bool CanSimulate() const { 18 | return simulator_ != nullptr; 19 | } 20 | 21 | CodeSimulator *Get() { 22 | DCHECK(CanSimulate()); 23 | return simulator_; 24 | } 25 | 26 | const CodeSimulator *Get() const { 27 | DCHECK(CanSimulate()); 28 | return simulator_; 29 | } 30 | 31 | private: 32 | CodeSimulator *simulator_; 33 | 34 | DISALLOW_COPY_AND_ASSIGN(CodeSimulatorContainer); 35 | }; 36 | 37 | 38 | } // namespace whale 39 | 40 | 41 | #endif // WHALE_SIMULATOR_CODE_SIMULATOR_CONTAINER_H_ 42 | 43 | 44 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/test/test_emulator.cc: -------------------------------------------------------------------------------- 1 | #include "base/logging.h" 2 | #include "dbi/arm64/inline_hook_arm64.h" 3 | #include "simulator/code_simulator_container.h" 4 | #include "simulator/code_simulator.h" 5 | #include "vixl/aarch64/macro-assembler-aarch64.h" 6 | #include "dbi/arm/decoder_arm.h" 7 | 8 | using namespace whale; //NOLINT 9 | using namespace whale::arm; //NOLINT 10 | using namespace whale::arm64; //NOLINT 11 | using namespace vixl::aarch64; //NOLINT 12 | 13 | #define __ masm-> 14 | 15 | void GenerateOriginFunction(MacroAssembler *masm) { 16 | Label label, label2; 17 | __ Mov(x1, 0); 18 | __ Cbz(x1, &label); 19 | __ Mov(x0, 111); 20 | __ B(&label2); 21 | __ Bind(&label); 22 | __ Mov(x0, 222); 23 | __ Bind(&label2); 24 | __ Ret(); 25 | masm->FinalizeCode(); 26 | } 27 | 28 | void GenerateReplaceFunction(MacroAssembler *masm) { 29 | __ Mov(x0, 999); 30 | __ Ret(); 31 | masm->FinalizeCode(); 32 | } 33 | 34 | 35 | int main() { 36 | CodeSimulatorContainer emulator(InstructionSet::kArm64); 37 | MacroAssembler masm_origin, masm_replace; 38 | GenerateOriginFunction(&masm_origin); 39 | GenerateReplaceFunction(&masm_replace); 40 | 41 | auto target = masm_origin.GetBuffer()->GetStartAddress(); 42 | auto replace = masm_replace.GetBuffer()->GetStartAddress(); 43 | emulator.Get()->RunFrom(target); 44 | LOG(INFO) << "Before Hook, result: "<< emulator.Get()->GetCReturnInt32(); 45 | intptr_t origin; 46 | Arm64InlineHook hook(target, reinterpret_cast(replace), &origin); 47 | hook.StartHook(); 48 | emulator.Get()->RunFrom(replace); 49 | LOG(INFO) << "After Hook, hooked result:"<< emulator.Get()->GetCReturnInt32(); 50 | emulator.Get()->RunFrom(origin); 51 | LOG(INFO) << "After Hook: origin result:"<< emulator.Get()->GetCReturnInt32(); 52 | } 53 | -------------------------------------------------------------------------------- /Common/ASMHooker/whale/whale/test/test_hook.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | char *(*Origin_getenv)(const char *); 7 | 8 | char *Hooked_getenv(const char *name) { 9 | if (!strcmp(name, "lody")) { 10 | return strdup("are you ok?"); 11 | } 12 | char *(*O)(const char *) = Origin_getenv; 13 | return O(name); 14 | } 15 | 16 | int main() { 17 | #if defined(__APPLE__) 18 | void *handle = dlopen("libc.dylib", RTLD_NOW); 19 | #else 20 | void *handle = dlopen("libc.so", RTLD_NOW); 21 | #endif 22 | assert(handle != nullptr); 23 | void *symbol = dlsym(handle, "getenv"); 24 | assert(symbol != nullptr); 25 | WInlineHookFunction( 26 | symbol, 27 | reinterpret_cast(Hooked_getenv), 28 | reinterpret_cast(&Origin_getenv) 29 | ); 30 | // WImportHookFunction( 31 | // "_getenv", 32 | // reinterpret_cast(Hooked_getenv), 33 | // reinterpret_cast(&Origin_getenv) 34 | // ); 35 | 36 | const char *val = getenv("lody"); 37 | std::cout << val; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /Common/ELFPatcher/.gitignore: -------------------------------------------------------------------------------- 1 | /autom4te.cache/ 2 | 3 | /aclocal.m4 4 | /configure 5 | /config.log 6 | /config.status 7 | /depcomp 8 | /install-sh 9 | /missing 10 | /build-aux/ 11 | 12 | /patchelf.spec 13 | /src/patchelf 14 | 15 | Makefile.in 16 | Makefile 17 | 18 | .deps 19 | *.o 20 | 21 | /tests/*.log 22 | /tests/*.trs 23 | /tests/no-rpath 24 | /tests/no-rpath-*.sh 25 | /tests/*.so 26 | -------------------------------------------------------------------------------- /Common/ELFPatcher/.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: xenial 3 | script: 4 | - ./bootstrap.sh 5 | - ./configure 6 | - make 7 | - cd tests && make check 8 | -------------------------------------------------------------------------------- /Common/ELFPatcher/BUGS: -------------------------------------------------------------------------------- 1 | Bug in Linux kernel, in fs/binfmt_elf.c: 2 | 3 | NEW_AUX_ENT( 3, AT_PHDR, load_addr + exec->e_phoff); 4 | 5 | This is wrong since the actual virtual address of the program headers 6 | may be somewhere else. 7 | -------------------------------------------------------------------------------- /Common/ELFPatcher/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src tests 2 | 3 | EXTRA_DIST = COPYING README patchelf.spec version $(man1_MANS) 4 | 5 | man1_MANS = patchelf.1 6 | 7 | doc_DATA = README 8 | -------------------------------------------------------------------------------- /Common/ELFPatcher/bootstrap.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | autoreconf --verbose --install --force --warnings=all 3 | -------------------------------------------------------------------------------- /Common/ELFPatcher/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([patchelf], m4_esyscmd([printf $(cat ./version)])) 2 | AC_CONFIG_SRCDIR([src/patchelf.cc]) 3 | AC_CONFIG_AUX_DIR([build-aux]) 4 | AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2 foreign color-tests serial-tests]) 5 | 6 | AM_PROG_CC_C_O 7 | AC_PROG_CXX 8 | 9 | PAGESIZE=auto 10 | AC_ARG_WITH([page-size], 11 | AS_HELP_STRING([--with-page-size=SIZE], [Specify default pagesize (default auto)]), 12 | PAGESIZE=$withval 13 | ) 14 | 15 | if test "$PAGESIZE" = auto; then 16 | if command -v getconf >/dev/null; then 17 | PAGESIZE=$(getconf PAGESIZE || getconf PAGE_SIZE) 18 | fi 19 | if test "$PAGESIZE" = auto -o -z "$PAGESIZE"; then 20 | PAGESIZE=4096 21 | fi 22 | fi 23 | 24 | AC_DEFINE_UNQUOTED(PAGESIZE, ${PAGESIZE}) 25 | AC_MSG_RESULT([Setting page size to ${PAGESIZE}]) 26 | 27 | AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile patchelf.spec]) 28 | AC_OUTPUT 29 | -------------------------------------------------------------------------------- /Common/ELFPatcher/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "inputs": { 3 | "nixpkgs": { 4 | "inputs": {}, 5 | "narHash": "sha256-yfhWbT0TL6NiCc5lCXauGsImnpDFNHV7ngjyUYrm6CY=", 6 | "originalUrl": "nixpkgs", 7 | "url": "github:edolstra/nixpkgs/d4a07f018e707b31a0eb7aff3f2838d01d53a0df" 8 | } 9 | }, 10 | "version": 3 11 | } 12 | -------------------------------------------------------------------------------- /Common/ELFPatcher/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | edition = 201909; 3 | 4 | description = "A tool for modifying ELF executables and libraries"; 5 | 6 | outputs = { self, nixpkgs }: 7 | 8 | let 9 | supportedSystems = [ "x86_64-linux" "i686-linux" "aarch64-linux" ]; 10 | forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system); 11 | in 12 | 13 | rec { 14 | 15 | overlay = final: prev: { 16 | 17 | patchelf-new = final.stdenv.mkDerivation { 18 | name = "patchelf-${hydraJobs.tarball.version}"; 19 | src = "${hydraJobs.tarball}/tarballs/*.tar.bz2"; 20 | }; 21 | 22 | }; 23 | 24 | hydraJobs = import ./release.nix { 25 | patchelfSrc = self; 26 | nixpkgs = nixpkgs; 27 | }; 28 | 29 | checks = forAllSystems (system: { 30 | build = hydraJobs.build.${system}; 31 | }); 32 | 33 | defaultPackage = forAllSystems (system: 34 | (import nixpkgs { 35 | inherit system; 36 | overlays = [ self.overlay ]; 37 | }).patchelf-new 38 | ); 39 | 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /Common/ELFPatcher/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := elfpatcher 6 | 7 | LOCAL_LDLIBS := 8 | 9 | LOCAL_SRC_FILES := ../src/patchelf.cc 10 | 11 | LOCAL_C_INCLUDES := 12 | LOCAL_LDFLAGS := 13 | 14 | LOCAL_CFLAGS := -DPAGESIZE=4096 -DPACKAGE_STRING=\"elfpatcher\" 15 | LOCAL_CPPFLAGS += $(LOCAL_CFLAGS) -std=gnu++11 16 | 17 | include $(BUILD_EXECUTABLE) 18 | -------------------------------------------------------------------------------- /Common/ELFPatcher/jni/Application.mk: -------------------------------------------------------------------------------- 1 | NDK_TOOLCHAIN_VERSION := clang 2 | APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 3 | APP_PLATFORM := android-21 4 | APP_STL := c++_static 5 | -------------------------------------------------------------------------------- /Common/ELFPatcher/patchelf.1: -------------------------------------------------------------------------------- 1 | .\" Process this file with 2 | .\" groff -man -Tascii foo.1 3 | .\" 4 | .TH PATCHELF 1 "JUNE 2010" PATCHELF "User Manuals" 5 | .SH NAME 6 | patchelf - Modify ELF files 7 | 8 | .SH SYNOPSIS 9 | .B patchelf 10 | .I OPTION 11 | .B 12 | .I FILE 13 | .B 14 | 15 | .SH DESCRIPTION 16 | 17 | PatchELF is a simple utility for modifying existing ELF executables 18 | and libraries. It can change the dynamic loader ("ELF interpreter") 19 | of executables and change the RPATH of executables and libraries. 20 | 21 | .SH OPTIONS 22 | 23 | The single option given operates on a given FILE, editing in place. 24 | 25 | .IP "--page-size SIZE" 26 | Uses the given page size instead of the default. 27 | 28 | .IP "--set-interpreter INTERPRETER" 29 | Change the dynamic loader ("ELF interpreter") of executable given to 30 | INTERPRETER. 31 | 32 | .IP --print-interpreter 33 | Prints the ELF interpreter of the executable. 34 | 35 | .IP --print-soname 36 | Prints DT_SONAME entry of .dynamic section. 37 | Raises an error if DT_SONAME doesn't exist. 38 | 39 | .IP "--set-soname SONAME" 40 | Sets DT_SONAME entry of a library to SONAME. 41 | 42 | .IP "--set-rpath RPATH" 43 | Change the RPATH of the executable or library to RPATH. 44 | 45 | .IP --remove-rpath 46 | Removes the DT_RPATH or DT_RUNPATH entry of the executable or library. 47 | 48 | .IP --shrink-rpath 49 | Remove from the RPATH all directories that do not contain a 50 | library referenced by DT_NEEDED fields of the executable or library. 51 | 52 | For instance, if an executable references one library libfoo.so, has 53 | an RPATH "/lib:/usr/lib:/foo/lib", and libfoo.so can only be found 54 | in /foo/lib, then the new RPATH will be "/foo/lib". 55 | 56 | .IP "--allowed-rpath-prefixes PREFIXES" 57 | Combined with the "--shrink-rpath" option, this can be used for 58 | further rpath tuning. For instance, if an executable has an RPATH 59 | "/tmp/build-foo/.libs:/foo/lib", it is probably desirable to keep 60 | the "/foo/lib" reference instead of the "/tmp" entry. 61 | 62 | .IP --print-rpath 63 | Prints the RPATH for an executable or library. 64 | 65 | .IP --force-rpath 66 | Forces the use of the obsolete DT_RPATH in the file instead of 67 | DT_RUNPATH. By default DT_RPATH is converted to DT_RUNPATH. 68 | 69 | .IP "--add-needed LIBRARY" 70 | Adds a declared dependency on a dynamic library (DT_NEEDED). 71 | This option can be give multiple times. 72 | 73 | .IP "--replace-needed LIB_ORIG LIB_NEW" 74 | Replaces a declared dependency on a dynamic library with another one (DT_NEEDED). 75 | This option can be give multiple times. 76 | 77 | .IP "--remove-needed LIBRARY" 78 | Removes a declared dependency on LIBRARY (DT_NEEDED entry). This 79 | option can be given multiple times. 80 | 81 | .IP "--no-default-lib" 82 | Marks the object that the search for dependencies of this object will ignore any 83 | default library search paths. 84 | 85 | .IP --debug 86 | Prints details of the changes made to the input file. 87 | 88 | .IP --version 89 | Shows the version of patchelf. 90 | 91 | .SH AUTHOR 92 | Eelco Dolstra 93 | 94 | .SH "SEE ALSO" 95 | .BR elf (5), 96 | .BR ld.so (8) 97 | 98 | 99 | -------------------------------------------------------------------------------- /Common/ELFPatcher/patchelf.spec.in: -------------------------------------------------------------------------------- 1 | Summary: A utility for patching ELF binaries 2 | 3 | Name: patchelf 4 | Version: @PACKAGE_VERSION@ 5 | Release: 1 6 | License: GPL 7 | Group: Development/Tools 8 | URL: http://nixos.org/patchelf.html 9 | Source0: %{name}-%{version}.tar.bz2 10 | BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot 11 | Prefix: /usr 12 | 13 | %description 14 | 15 | PatchELF is a simple utility for modifying existing ELF executables and 16 | libraries. It can change the dynamic loader ("ELF interpreter") of 17 | executables and change the RPATH of executables and libraries. 18 | 19 | %prep 20 | %setup -q 21 | 22 | %build 23 | ./configure --prefix=%{_prefix} 24 | make 25 | make check 26 | 27 | %install 28 | rm -rf $RPM_BUILD_ROOT 29 | make DESTDIR=$RPM_BUILD_ROOT install 30 | # rpmbuild automatically strips... strip $RPM_BUILD_ROOT/%%{_bindir}/* || true 31 | 32 | %clean 33 | rm -rf $RPM_BUILD_ROOT 34 | 35 | %files 36 | %{_bindir}/patchelf 37 | %doc %{_docdir}/patchelf/README 38 | %{_mandir}/man1/patchelf.1.gz 39 | -------------------------------------------------------------------------------- /Common/ELFPatcher/src/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CXXFLAGS = -Wall -std=c++11 -D_FILE_OFFSET_BITS=64 2 | 3 | bin_PROGRAMS = patchelf 4 | 5 | patchelf_SOURCES = patchelf.cc elf.h 6 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/Makefile.am: -------------------------------------------------------------------------------- 1 | LIBS = 2 | 3 | check_PROGRAMS = simple main main-scoped big-dynstr no-rpath 4 | 5 | no_rpath_arch_TESTS = \ 6 | no-rpath-amd64.sh \ 7 | no-rpath-armel.sh \ 8 | no-rpath-armhf.sh \ 9 | no-rpath-hurd-i386.sh \ 10 | no-rpath-i386.sh \ 11 | no-rpath-ia64.sh \ 12 | no-rpath-kfreebsd-amd64.sh \ 13 | no-rpath-kfreebsd-i386.sh \ 14 | no-rpath-mips.sh \ 15 | no-rpath-mipsel.sh \ 16 | no-rpath-powerpc.sh \ 17 | no-rpath-s390.sh \ 18 | no-rpath-sh4.sh \ 19 | no-rpath-sparc.sh 20 | 21 | src_TESTS = \ 22 | plain-fail.sh plain-run.sh shrink-rpath.sh set-interpreter-short.sh \ 23 | set-interpreter-long.sh set-rpath.sh no-rpath.sh big-dynstr.sh \ 24 | set-rpath-library.sh soname.sh shrink-rpath-with-allowed-prefixes.sh 25 | 26 | build_TESTS = \ 27 | $(no_rpath_arch_TESTS) 28 | 29 | TESTS = $(src_TESTS) $(build_TESTS) 30 | 31 | EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh 32 | 33 | TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 34 | 35 | $(no_rpath_arch_TESTS): no-rpath-prebuild.sh 36 | @ln -s $< $@ 37 | 38 | CLEANFILES = big-dynstr.c 39 | clean-local: 40 | $(RM) -r scratch $(no_rpath_arch_TESTS) 41 | 42 | # by default, use -fpic to compile 43 | AM_CFLAGS = -fpic 44 | LDFLAGS_local = -Wl,--disable-new-dtags -Wl,-rpath-link=. -L. $(AM_LDFLAGS) 45 | LDFLAGS_sharedlib = -Wl,--disable-new-dtags -shared -L. $(AM_LDFLAGS) 46 | export NIX_DONT_SET_RPATH=1 47 | export NIX_LDFLAGS= 48 | 49 | simple_SOURCES = simple.c 50 | # no -fpic for simple.o 51 | simple_CFLAGS = 52 | 53 | main_SOURCES = main.c 54 | main_LDADD = -lfoo $(AM_LDADD) 55 | main_DEPENDENCIES = libfoo.so 56 | main_LDFLAGS = $(LDFLAGS_local) 57 | 58 | main_scoped_SOURCES = main.c 59 | main_scoped_LDADD = -lfoo-scoped $(AM_LDADD) 60 | main_scoped_DEPENDENCIES = libfoo-scoped.so 61 | main_scoped_LDFLAGS = $(LDFLAGS_local) 62 | 63 | big-dynstr.c: main.c 64 | cat $< > big-dynstr.c 65 | for i in $$(seq 1 2000); do echo "void f$$i(void) { };" >> big-dynstr.c; done 66 | 67 | nodist_big_dynstr_SOURCES = big-dynstr.c 68 | big_dynstr_LDADD = -lfoo $(AM_LDADD) 69 | big_dynstr_DEPENDENCIES = libfoo.so 70 | big_dynstr_LDFLAGS = $(LDFLAGS_local) 71 | 72 | # declare local shared libraries as programs as: 73 | # - without libtool, only archives (static libraries) can be built by automake 74 | # - with libtool, it is difficult to control options 75 | # - with libtool, it is not possible to compile convenience *dynamic* libraries :-( 76 | check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so 77 | 78 | libfoo_so_SOURCES = foo.c 79 | libfoo_so_LDADD = -lbar $(AM_LDADD) 80 | libfoo_so_DEPENDENCIES = libbar.so 81 | libfoo_so_LDFLAGS = $(LDFLAGS_sharedlib) 82 | 83 | libfoo_scoped_so_SOURCES = foo.c 84 | libfoo_scoped_so_LDADD = -lbar-scoped $(AM_LDADD) 85 | libfoo_scoped_so_DEPENDENCIES = libbar-scoped.so 86 | libfoo_scoped_so_LDFLAGS = $(LDFLAGS_sharedlib) 87 | 88 | libbar_so_SOURCES = bar.c 89 | libbar_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-rpath,`pwd`/no-such-path 90 | 91 | libbar_scoped_so_SOURCES = bar.c 92 | libbar_scoped_so_LDFLAGS = $(LDFLAGS_sharedlib) 93 | 94 | libsimple_so_SOURCES = simple.c 95 | libsimple_so_LDFLAGS = $(LDFLAGS_sharedlib) 96 | 97 | no_rpath_SOURCES = no-rpath.c 98 | # no -fpic for no-rpath.o 99 | no_rpath_CFLAGS = 100 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/bar.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int bar() 4 | { 5 | printf("This is bar()!\n"); 6 | return 34; 7 | } 8 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/big-dynstr.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | rm -rf ${SCRATCH} 5 | mkdir -p ${SCRATCH} 6 | mkdir -p ${SCRATCH}/libsA 7 | mkdir -p ${SCRATCH}/libsB 8 | 9 | cp big-dynstr ${SCRATCH}/ 10 | cp libfoo.so ${SCRATCH}/libsA/ 11 | cp libbar.so ${SCRATCH}/libsB/ 12 | 13 | oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/big-dynstr) 14 | if test -z "$oldRPath"; then oldRPath="/oops"; fi 15 | ../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/big-dynstr 16 | 17 | if test "$(uname)" = FreeBSD; then 18 | export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB 19 | fi 20 | 21 | exitCode=0 22 | cd ${SCRATCH} && ./big-dynstr || exitCode=$? 23 | 24 | if test "$exitCode" != 46; then 25 | echo "bad exit code!" 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/foo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Include a bogus .interp section in libfoo.so (NIXPKGS-98). 4 | Borrowed from Glibc. */ 5 | const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp"))) = "/foo/bar"; 6 | 7 | int bar(); 8 | 9 | int foo() 10 | { 11 | printf("This is foo()!\n"); 12 | return 12 + bar(); 13 | } 14 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char buf[16 * 1024 * 1024]; 4 | 5 | int foo(); 6 | 7 | int main(int argc, char * * argv) 8 | { 9 | int x; 10 | printf("Hello World\n"); 11 | x = foo(); 12 | printf("Result is %d\n", x); 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-amd64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-amd64 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-armel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-armel -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-armhf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-armhf -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-hurd-i386: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-hurd-i386 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-i386: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-i386 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-ia64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-ia64 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-kfreebsd-amd64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-kfreebsd-amd64 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-kfreebsd-i386: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-kfreebsd-i386 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-mips: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-mips -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-mipsel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-mipsel -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-powerpc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-powerpc -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-s390: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-s390 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-sh4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-sh4 -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-sparc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/ELFPatcher/tests/no-rpath-prebuild/no-rpath-sparc -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Hello world\n"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/no-rpath.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | rm -rf ${SCRATCH} 5 | mkdir -p ${SCRATCH} 6 | 7 | cp no-rpath ${SCRATCH}/ 8 | 9 | oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) 10 | if test -n "$oldRPath"; then exit 1; fi 11 | ../src/patchelf \ 12 | --set-interpreter "$(../src/patchelf --print-interpreter ../src/patchelf)" \ 13 | --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath 14 | 15 | newRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) 16 | if ! echo "$newRPath" | grep -q '/foo:/bar'; then 17 | echo "incomplete RPATH" 18 | exit 1 19 | fi 20 | 21 | cd ${SCRATCH} && ./no-rpath 22 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/plain-fail.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | if ./main; then 3 | exit 1 4 | fi 5 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/plain-run.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | LD_LIBRARY_PATH=. ./main 3 | exitCode=$? 4 | if test "$exitCode" != 46; then 5 | echo "bad exit code!" 6 | exit 1 7 | fi 8 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/set-interpreter-long.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | ./simple 5 | 6 | oldInterpreter=$(../src/patchelf --print-interpreter ./simple) 7 | echo "current interpreter is $oldInterpreter" 8 | 9 | if test "$(uname)" = Linux; then 10 | echo "running with explicit interpreter..." 11 | "$oldInterpreter" ./simple 12 | fi 13 | 14 | rm -rf ${SCRATCH} 15 | mkdir -p ${SCRATCH} 16 | 17 | newInterpreter=$(pwd)/${SCRATCH}/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii 18 | cp simple ${SCRATCH}/ 19 | ../src/patchelf --set-interpreter "$newInterpreter" ${SCRATCH}/simple 20 | 21 | echo "running with missing interpreter..." 22 | if ${SCRATCH}/simple; then 23 | echo "simple works, but it shouldn't" 24 | exit 1 25 | fi 26 | 27 | echo "running with new interpreter..." 28 | ln -s "$oldInterpreter" "$newInterpreter" 29 | ${SCRATCH}/simple 30 | 31 | if test "$(uname)" = Linux; then 32 | echo "running with explicit interpreter..." 33 | "$oldInterpreter" ${SCRATCH}/simple 34 | fi 35 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/set-interpreter-short.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | ./simple 5 | 6 | oldInterpreter=$(../src/patchelf --print-interpreter ./simple) 7 | echo "current interpreter is $oldInterpreter" 8 | 9 | rm -rf ${SCRATCH} 10 | mkdir -p ${SCRATCH} 11 | 12 | cp simple ${SCRATCH}/ 13 | ../src/patchelf --set-interpreter /oops ${SCRATCH}/simple 14 | 15 | echo "running with missing interpreter..." 16 | if ${SCRATCH}/simple; then 17 | echo "simple works, but it shouldn't" 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/set-rpath-library.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | if test "$(uname)" = FreeBSD; then 5 | echo "skipping on FreeBSD" 6 | exit 0 7 | fi 8 | 9 | rm -rf ${SCRATCH} 10 | mkdir -p ${SCRATCH} 11 | mkdir -p ${SCRATCH}/libsA 12 | mkdir -p ${SCRATCH}/libsB 13 | 14 | cp main-scoped ${SCRATCH}/ 15 | cp libfoo-scoped.so ${SCRATCH}/libsA/ 16 | cp libbar-scoped.so ${SCRATCH}/libsB/ 17 | 18 | oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main-scoped) 19 | if test -z "$oldRPath"; then oldRPath="/oops"; fi 20 | ../src/patchelf --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main-scoped 21 | 22 | # "main" contains libbar in its RUNPATH, but that's ignored when 23 | # resolving libfoo. So libfoo won't find libbar and this will fail. 24 | exitCode=0 25 | (cd ${SCRATCH} && ./main-scoped) || exitCode=$? 26 | 27 | if test "$exitCode" = 46; then 28 | echo "expected failure" 29 | exit 1 30 | fi 31 | 32 | # So set an RUNPATH on libfoo as well. 33 | oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/libsA/libfoo-scoped.so) 34 | if test -z "$oldRPath"; then oldRPath="/oops"; fi 35 | ../src/patchelf --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/libsA/libfoo-scoped.so 36 | 37 | exitCode=0 38 | (cd ${SCRATCH} && ./main-scoped) || exitCode=$? 39 | 40 | if test "$exitCode" != 46; then 41 | echo "bad exit code!" 42 | exit 1 43 | fi 44 | 45 | # Remove the libbar PATH from main using --shrink-rpath. 46 | ../src/patchelf --shrink-rpath ${SCRATCH}/main-scoped 47 | if ../src/patchelf --print-rpath ${SCRATCH}/main-scoped | grep /libsB; then 48 | echo "shrink failed" 49 | exit 1 50 | fi 51 | 52 | # And it should still run. 53 | exitCode=0 54 | (cd ${SCRATCH} && ./main-scoped) || exitCode=$? 55 | 56 | if test "$exitCode" != 46; then 57 | echo "bad exit code!" 58 | exit 1 59 | fi 60 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/set-rpath.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | rm -rf ${SCRATCH} 5 | mkdir -p ${SCRATCH} 6 | mkdir -p ${SCRATCH}/libsA 7 | mkdir -p ${SCRATCH}/libsB 8 | 9 | cp main ${SCRATCH}/ 10 | cp libfoo.so ${SCRATCH}/libsA/ 11 | cp libbar.so ${SCRATCH}/libsB/ 12 | 13 | oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main) 14 | if test -z "$oldRPath"; then oldRPath="/oops"; fi 15 | ../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main 16 | 17 | if test "$(uname)" = FreeBSD; then 18 | export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB 19 | fi 20 | 21 | exitCode=0 22 | (cd ${SCRATCH} && ./main) || exitCode=$? 23 | 24 | if test "$exitCode" != 46; then 25 | echo "bad exit code!" 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/shrink-rpath-with-allowed-prefixes.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | rm -rf ${SCRATCH} 5 | mkdir -p ${SCRATCH} 6 | mkdir -p ${SCRATCH}/libsA 7 | mkdir -p ${SCRATCH}/libsB 8 | 9 | cp main ${SCRATCH}/ 10 | cp libfoo.so libbar.so ${SCRATCH}/libsA/ 11 | cp libfoo.so libbar.so ${SCRATCH}/libsB/ 12 | 13 | oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main) 14 | if test -z "$oldRPath"; then oldRPath="/oops"; fi 15 | pathA="$(pwd)/${SCRATCH}/libsA" 16 | pathB="$(pwd)/${SCRATCH}/libsB" 17 | ../src/patchelf --force-rpath --set-rpath $oldRPath:$pathA:$pathB ${SCRATCH}/main 18 | 19 | cp ${SCRATCH}/main ${SCRATCH}/mainA 20 | cp ${SCRATCH}/main ${SCRATCH}/mainB 21 | 22 | ../src/patchelf --shrink-rpath ${SCRATCH}/main 23 | ../src/patchelf --shrink-rpath --allowed-rpath-prefixes $oldRPath:$pathA ${SCRATCH}/mainA 24 | ../src/patchelf --shrink-rpath --allowed-rpath-prefixes $oldRPath:$pathB ${SCRATCH}/mainB 25 | 26 | check() { 27 | exe=$1 28 | mustContain=$2 29 | mustNotContain=$3 30 | 31 | rpath=$(../src/patchelf --print-rpath $exe) 32 | echo "RPATH of $exe after: $rpath" 33 | 34 | if ! echo "$rpath" | grep -q $mustContain; then 35 | echo "RPATH didn't contain '$mustContain' when it should have" 36 | exit 1 37 | fi 38 | 39 | if echo "$rpath" | grep -q $mustNotContain; then 40 | echo "RPATH contained '$mustNotContain' when it shouldn't have" 41 | exit 1 42 | fi 43 | } 44 | 45 | check ${SCRATCH}/main $pathA $pathB 46 | check ${SCRATCH}/mainA $pathA $pathB 47 | check ${SCRATCH}/mainB $pathB $pathA 48 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/shrink-rpath.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | rpath=$(../src/patchelf --print-rpath ./libbar.so) 5 | echo "RPATH before: $rpath" 6 | if ! echo "$rpath" | grep -q /no-such-path; then 7 | echo "incomplete RPATH" 8 | exit 1 9 | fi 10 | 11 | rm -rf ${SCRATCH} 12 | mkdir -p ${SCRATCH} 13 | cp libbar.so ${SCRATCH}/ 14 | ../src/patchelf --shrink-rpath ${SCRATCH}/libbar.so 15 | 16 | rpath=$(../src/patchelf --print-rpath ${SCRATCH}/libbar.so) 17 | echo "RPATH after: $rpath" 18 | if echo "$rpath" | grep -q /no-such-path; then 19 | echo "RPATH not shrunk" 20 | exit 1 21 | fi 22 | 23 | cp libfoo.so ${SCRATCH}/ 24 | 25 | exitCode=0 26 | cd ${SCRATCH} && LD_LIBRARY_PATH=. ../../main || exitCode=$? 27 | 28 | if test "$exitCode" != 46; then 29 | echo "bad exit code!" 30 | exit 1 31 | fi 32 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char buf[16 * 1024 * 1024]; 4 | 5 | int main(int argc, char * * argv) 6 | { 7 | printf("Hello World\n"); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /Common/ELFPatcher/tests/soname.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh -e 2 | SCRATCH=scratch/$(basename $0 .sh) 3 | 4 | rm -rf ${SCRATCH} 5 | mkdir -p ${SCRATCH} 6 | 7 | cp libsimple.so ${SCRATCH}/ 8 | 9 | # set an initial DT_SONAME entry 10 | ../src/patchelf --set-soname libsimple.so.1.0 ${SCRATCH}/libsimple.so 11 | newSoname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so) 12 | if test "$newSoname" != libsimple.so.1.0; then 13 | echo "failed --set-soname test. Expected newSoname: libsimple.so.1.0, got: $newSoname" 14 | exit 1 15 | fi 16 | 17 | # print DT_SONAME 18 | soname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so) 19 | if test "$soname" != libsimple.so.1.0; then 20 | echo "failed --print-soname test. Expected soname: libsimple.so.1.0, got: $soname" 21 | exit 1 22 | fi 23 | 24 | # replace DT_SONAME entry 25 | ../src/patchelf --set-soname libsimple.so.1.1 ${SCRATCH}/libsimple.so 26 | newSoname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so) 27 | if test "$newSoname" != libsimple.so.1.1; then 28 | echo "failed --set-soname test. Expected newSoname: libsimple.so.1.1, got: $newSoname" 29 | exit 1 30 | fi 31 | -------------------------------------------------------------------------------- /Common/ELFPatcher/version: -------------------------------------------------------------------------------- 1 | 0.10 -------------------------------------------------------------------------------- /Common/PLTHooker/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | 6 | LOCAL_MODULE := libElfHook_static 7 | 8 | LOCAL_SRC_FILES := \ 9 | src/elf_common.cpp \ 10 | src/elf_hooker.cpp \ 11 | src/elf_module.cpp 12 | 13 | LOCAL_C_INCLUDES := 14 | 15 | LOCAL_LDFLAGS := 16 | 17 | #LOCAL_STATIC_LIBRARIES := 18 | LOCAL_SHARED_LIBRARIES := stdc++ 19 | 20 | LOCAL_CFLAGS := \ 21 | -Wno-write-strings \ 22 | -DHAVE_LITTLE_ENDIAN \ 23 | -Werror 24 | 25 | include $(BUILD_STATIC_LIBRARY) 26 | 27 | #################################### 28 | 29 | include $(CLEAR_VARS) 30 | 31 | LOCAL_MODULE := ElfHook 32 | LOCAL_LDLIBS := -llog 33 | LOCAL_SRC_FILES := \ 34 | src/main.cpp 35 | 36 | LOCAL_C_INCLUDES := 37 | 38 | LOCAL_LDFLAGS := 39 | 40 | LOCAL_STATIC_LIBRARIES := ElfHook_static 41 | LOCAL_SHARED_LIBRARIES := stdc++ 42 | 43 | LOCAL_CFLAGS := \ 44 | -Wno-write-strings \ 45 | -DHAVE_LITTLE_ENDIAN \ 46 | -DELFHOOK_STANDALONE=0 47 | include $(BUILD_SHARED_LIBRARY) 48 | 49 | #################################### 50 | 51 | include $(CLEAR_VARS) 52 | 53 | LOCAL_MODULE := ElfHook.out 54 | LOCAL_LDLIBS := -llog 55 | LOCAL_SRC_FILES := \ 56 | src/main.cpp 57 | 58 | LOCAL_C_INCLUDES := 59 | 60 | LOCAL_LDFLAGS := -fPIC -pie 61 | 62 | LOCAL_STATIC_LIBRARIES := ElfHook_static 63 | LOCAL_SHARED_LIBRARIES := stdc++ 64 | 65 | LOCAL_CFLAGS := \ 66 | -Wno-write-strings \ 67 | -DHAVE_LITTLE_ENDIAN \ 68 | -DELFHOOK_STANDALONE=1 69 | 70 | include $(BUILD_EXECUTABLE) 71 | -------------------------------------------------------------------------------- /Common/PLTHooker/Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | SRC_DIR = ./src 4 | OBJ_DIR = ./objs 5 | BIN_DIR = ./bin 6 | 7 | 8 | JNIFLAGS = APP_BUILD_SCRIPT=./Android.mk 9 | JNIFLAGS += APP_ABI=arm64-v8a,armeabi-v7a 10 | JNIFLAGS += APP_PLATFORM=android-23 11 | JNIFLAGS += APP_STL=stlport_static 12 | 13 | JNILIBPATH = ./Demo/app/src/main/jniLibs 14 | 15 | 16 | all: 17 | @echo '\n [NDK-BUILD] '$(PWD)'\n\n';ndk-build NDK_PROJECT_PATH=. NDK_OUT=$(OBJ_DIR) NDK_LIBS_OUT=$(BIN_DIR) $(JNIFLAGS) 18 | 19 | clean: 20 | @echo '\n [NDK-BUILD] clean'$(PWD)'\n\n';ndk-build clean NDK_PROJECT_PATH=. NDK_OUT=$(OBJ_DIR) NDK_LIBS_OUT=$(BIN_DIR) $(JNIFLAGS) 21 | 22 | install : all 23 | @echo '[CP] ' $(BIN_DIR)/armeabi-v7a/libElfHook.so $(JNILIBPATH)/armeabi-v7a/libElfHook.so; cp $(BIN_DIR)/armeabi-v7a/libElfHook.so $(JNILIBPATH)/armeabi-v7a/libElfHook.so 24 | @echo '[CP] ' $(BIN_DIR)/arm64-v8a/libElfHook.so $(JNILIBPATH)/arm64-v8a/libElfHook.so; cp $(BIN_DIR)/arm64-v8a/libElfHook.so $(JNILIBPATH)/arm64-v8a/libElfHook.so 25 | -------------------------------------------------------------------------------- /Common/PLTHooker/README.md: -------------------------------------------------------------------------------- 1 | ## 0x01 Brief About ElfHook 2 | 3 |   这份ElfHook的代码参考boyliang的AllHookInOne, 修复AllHookInOne的 4 | ElfHook中的一些问题,同时也解决我们项目中遇到的一些问题。 5 | 6 | - **NOT** DT_HAST in .dynmaic section,but .gun.hash instead. 7 | 8 | - **NOT** DT_REL and DT_RELSZ in .dynmaic section, but DT_ANDROID_REL and DT_ANDROID_RELSZ instead. 9 | 10 | - 计算动态库加载的base_addr是错误的,应该使用bias_addr来计算出ehdr、phdr和shdr之外的所有地址。 11 | 12 | - 替换函数时,修改page的读写权限时,在SEAndroid上PROT_EXEC和PROT_WRITE同时设置**可能**会导致异常, 13 | 14 | - after hook "dlopen" function, how to get base_addr from return value of old dlopen in new dlopen function. 15 | 16 | - support aarch64 (arm64-v8a) 17 | 18 | ref: 19 | 20 |  AllHookInOne : [https://github.com/boyliang/AllHookInOne.git] 21 | 22 |  AllHookInOne说明 : [http://bbs.pediy.com/showthread.php?p=1328038] 23 | 24 |  bionic : [https://android.googlesource.com/platform/bionic] 25 | 26 | 27 | ## 0x02 How To Build 28 | 29 | #### Export android ndk path 30 | 31 | > export -p PATH=$PATH:$ANDROID_NDK 32 | 33 | 34 | #### Build 35 | 36 | > make 37 | 38 | > make clean 39 | 40 | > make install # copy libElfHook.so to jniLibs dir in Demo. 41 | 42 | #### or 43 | 44 | > ndk-build NDK_PROJECT_PATH=. NDK_OUT=./objs NDK_LIBS_OUT=./bin APP_BUILD_SCRIPT=./Android.mk APP_PLATFORM=android-23 APP_ABI=arm64-v8a,armeabi-v7a APP_STL=stlport_static 45 | 46 | ## 0x03 How To Use 47 | 48 | 49 | elf_module is a shared library or executable, elf_hooker is wrapper of hook function. 50 | 51 | - bool elf_hooker::phrase_proc_maps() 52 | 53 | phrase /proc/self/maps to create all elf modules have been loadded 54 | 55 | - void elf_hooker::dump_module_list() 56 | 57 | print all elf moudle's info, base addr and full path. 58 | 59 | - void elf_hooker::set_prehook_cb( prehook_cb ): 60 | 61 | set a callback function, which would be invoked before hooked. if it return false, prehook_cb function like this: 62 | 63 | > bool prehook_cb(const char* module_name, const char* func_name); 64 | 65 | >  module_name: the full filename of shared library or executable. 66 | 67 | >  func_name: function name would be hooked. 68 | 69 | - void elf_hooker::hook_all_modules(const char \*func_name, void \*pfn_new, void\*\* ppfn_old) 70 | 71 | hook a function of all the modules, **MUST** call phrase_proc_maps() before hook_all_modules() 72 | 73 | >  func_name: the name of function that will be hooked. 74 | 75 | >  pfn_new: new function pointer 76 | 77 | >  ppfn_old: return raw function pointer, ppfn_old **MUST NOT** be NULL 78 | 79 | - bool elf_hooker::hook(elf_module \*module, const char\* func_name, void \*pfn_new, void \*\*ppfn_old) 80 | 81 | hook a function of a single module. 82 | 83 | >  module: pointer of elf_module. 84 | 85 | >  other parameters is the same as hook_all_modules() 86 | -------------------------------------------------------------------------------- /Common/PLTHooker/config.mk: -------------------------------------------------------------------------------- 1 | 2 | 3 | ######### 安装路径 ########## 4 | 5 | ifndef PREFIX 6 | PREFIX = /usr 7 | endif 8 | 9 | EXEC = 10 | 11 | ANDROID_NDK = /Users/wuxin/Library/Android/ndk 12 | CROSS_PREFIX = arm-linux-androideabi- 13 | SYSROOT = $(ANDROID_NDK)/platforms/android-19/arch-arm 14 | 15 | STL_PORT = $(ANDROID_NDK)/sources/cxx-stl/stlport 16 | 17 | CC = $(CROSS_PREFIX)gcc 18 | AR = $(CROSS_PREFIX)ar 19 | LD = $(CROSS_PREFIX)gcc 20 | RANLIB = $(CROSS_PREFIX)ranlib 21 | STRIP = $(CROSS_PREFIX)strip 22 | CFLAGS += -fPIE -Werror --sysroot=$(SYSROOT) -DELFHOOK_STANDALONE=1 23 | CFLAGS += -I$(STL_PORT)/stlport 24 | LDFLAGS += --sysroot=$(SYSROOT) 25 | LDFLAGS += $(STL_PORT)/libs/armeabi-v7a/libstlport_static.a 26 | LDFLAGS += -fPIE -pie -lstdc++ 27 | JNIFLAGS = APP_BUILD_SCRIPT=./Android.mk 28 | JNIFLAGS += APP_ABI=arm64-v8a,armeabi-v7a 29 | JNIFLAGS += APP_PLATFORM=android-23 30 | JNIFLAGS += APP_STL=stlport_static 31 | EXTRA_OBJS += 32 | -------------------------------------------------------------------------------- /Common/PLTHooker/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := plthooker 6 | 7 | LOCAL_LDLIBS := -llog 8 | 9 | LOCAL_SRC_FILES := \ 10 | ../src/elf_common.cpp \ 11 | ../src/elf_hooker.cpp \ 12 | ../src/elf_module.cpp 13 | 14 | LOCAL_C_INCLUDES := 15 | 16 | LOCAL_LDFLAGS := 17 | 18 | LOCAL_CFLAGS := -Wno-write-strings \ 19 | -DHAVE_LITTLE_ENDIAN 20 | 21 | include $(BUILD_STATIC_LIBRARY) 22 | -------------------------------------------------------------------------------- /Common/PLTHooker/jni/Application.mk: -------------------------------------------------------------------------------- 1 | NDK_TOOLCHAIN_VERSION := clang 2 | APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 3 | APP_PLATFORM := android-21 4 | APP_STL := c++_static 5 | -------------------------------------------------------------------------------- /Common/PLTHooker/src/elf_common.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/Common/PLTHooker/src/elf_common.cpp -------------------------------------------------------------------------------- /Common/PLTHooker/src/elf_hooker.h: -------------------------------------------------------------------------------- 1 | #if !defined(__ELF_HOOKER_H__) 2 | #define __ELF_HOOKER_H__ 3 | 4 | 5 | #include 6 | #include 7 | 8 | #include "elf_module.h" 9 | 10 | class elf_hooker { 11 | 12 | public: 13 | elf_hooker(); 14 | ~elf_hooker(); 15 | 16 | 17 | bool phrase_proc_maps(); 18 | void dump_module_list(); 19 | 20 | // void* caculate_base_addr_from_soinfo_pointer(void* soinfo_addr); 21 | /* * 22 | prehook_cb invoked before really hook, 23 | if prehook_cb NOT set or return true, this module will be hooked, 24 | if prehook_cb set and return false, this module will NOT be hooked, 25 | */ 26 | inline void set_prehook_cb(bool (*pfn)(const char*, const char*)) { this->m_prehook_cb = pfn; } 27 | inline bool hook(elf_module* module, const char *func_name, void *pfn_new, void **ppfn_old) 28 | { 29 | return module->hook(func_name, pfn_new, ppfn_old); 30 | } 31 | 32 | void hook_all_modules(const char* func_name, void* pfn_new, void** ppfn_old); 33 | void dump_proc_maps(); 34 | protected: 35 | 36 | bool phrase_proc_base_addr(char* addr, void** pbase_addr, void** pend_addr); 37 | bool phrase_dev_num(char* devno, int *pmajor, int *pminor); 38 | 39 | protected: 40 | 41 | std::map m_modules; 42 | bool (*m_prehook_cb)(const char* module_name, const char* func_name); 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /Common/iOSUnicorn/ios_clang: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ''' 4 | This file is used to patch Unicorn build compiler for iOS arm64 on macOS. 5 | 6 | How to use: 7 | 1. export CC=/path/to/ios_clang on a shell; 8 | 2. in the unicorn source root directory, run make command; 9 | 3. after building, the libunicorn result file is now for iOS arm64 platform. 10 | 11 | If you have any advises, We are happy to hear from you. 12 | 13 | 14 | Follow us: 15 | ---------------------------------------------------------------------- 16 | Email 971159199@qq.com 17 | 公众号 刘柏江 18 | 头条 刘柏江 19 | 百家号 刘柏江VM 20 | 微博 刘柏江VM 21 | 码云 https://gitee.com/geekneo/ 22 | ---------------------------------------------------------------------- 23 | ''' 24 | 25 | import os 26 | import sys 27 | import subprocess 28 | 29 | def main(args): 30 | newargs = [ '/usr/bin/clang' ] 31 | # we'll patch all x86* related compiler args to arm64 32 | for i in range(1, len(args)): 33 | if 1 and (args[i] == 'x86_64' or args[i] == '-shared'): 34 | if args[i] == '-shared': 35 | newargs.append(args[i]) 36 | newargs.append('-arch') 37 | newargs.append('arm64') 38 | newargs.append('-target') 39 | newargs.append('arm64-apple-ios9.0') 40 | newargs.append('-isysroot') 41 | newargs.append('/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk') 42 | else: 43 | newargs.append(args[i].replace('i386', 'aarch64')) 44 | # print(newargs) 45 | proc = subprocess.Popen(newargs) 46 | proc.wait() 47 | sys.exit(proc.returncode) 48 | 49 | if __name__ == '__main__': 50 | main(sys.argv) 51 | -------------------------------------------------------------------------------- /Common/iOSUnicorn/patch.md: -------------------------------------------------------------------------------- 1 | After building unicorn with ios_clang, you'll get a crash when executing uc_emu_start. 2 | So, what the hell ? 3 | * 1.qemu uses malloc to allocate the dynamic executable page for 0x800000 bytes, but pages which are allocated by malloc can't be executable by default in iOS. You should patch qemu to use vm_allocate mach API; 4 | * 2.If the page is writable, then it can't be executable in iOS. You should mprotect it to PROT_READ|PROT_EXEC; 5 | 6 | OK, if you notice these limits, the solution is simple, wish you to solve this crash issue by yourself. Have fun with unicorn. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 刘柏江 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PantaEngine/README.md: -------------------------------------------------------------------------------- 1 | PantaEngine, a new arm/arm64 execution engine for Panta Android Emulator. 2 | 3 | #### Description 4 | 5 | TODO: 6 | 7 | 8 | Follow us for update or bug report: 9 | 10 | |Platform|Account|QRCode| 11 | |-|-|-| 12 | |Email|971159199@qq.com|.| 13 | |公众号|刘柏江|![gongzhonghao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/gongzhonghao.jpeg)| 14 | |百家号|刘柏江VM|![baijiahao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/baijiahao.jpeg)| 15 | |微博|刘柏江VM|![weibo](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/weibo.jpeg)| 16 | |头条|刘柏江|![toutiao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/toutiao.jpeg)| 17 | |码云|https://gitee.com/geekneo/|.| 18 | 19 | 20 | #### Version History 21 | 22 | TODO: 23 | 24 | 25 | #### Known Issue 26 | 27 | TODO: 28 | 29 | 30 | #### Screenshot 31 | 32 | TODO: 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Virtual Code Framework for V-CPU/VMProtect/ARM-Translator. 2 | 3 | #### Description 4 | 5 | * PantaEngine : A new arm/arm64 execution engine for Panta Android Emulator; 6 | * UltimateVMP : Virtual Machine Protect for iOS/Android native binary file; 7 | * UnicornVM-iOS : Virtual CPU based on unicorn for iOS arm64; 8 | * UnicornVM-V7 : Virtual CPU based on unicorn for Android armeabi-v7a; 9 | * UnicornVM-V8 : Virtual CPU based on unicorn for Android arm64-v8a; 10 | 11 | 12 | Follow us for update or bug report: 13 | 14 | |Platform|Account|QRCode| 15 | |-|-|-| 16 | |Email|971159199@qq.com|.| 17 | |公众号|刘柏江|![gongzhonghao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/gongzhonghao.jpeg)| 18 | |百家号|刘柏江VM|![baijiahao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/baijiahao.jpeg)| 19 | |微博|刘柏江VM|![weibo](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/weibo.jpeg)| 20 | |头条|刘柏江|![toutiao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/toutiao.jpeg)| 21 | |码云|https://gitee.com/geekneo/|.| 22 | 23 | 24 | #### Version History 25 | 26 | 2020.03.03-v1.0.0: 27 | 28 | * UnicornVM解释器添加vcop_ifetch回调操作码; 29 | 30 | 2020.02.29-v1.0.0: 31 | 32 | * UnicornVM-ARMV8(Android)发布初始版本; 33 | * UnicornVM-iOS(ARM64)发布初始版本; 34 | 35 | 2020.02.21-v0.9.0: 36 | 37 | * UnicornVM-ARMV8(Android)发布初始预览版; 38 | 39 | 2020.02.19-v0.9.0: 40 | 41 | * UnicornVM-iOS(ARM64)发布初始预览版; 42 | 43 | 2020.02.10-v1.0.0: 44 | 45 | * UnicornVM-ARMV7(Android)发布初始版本; 46 | 47 | 2020.02.03-v0.9.0: 48 | 49 | * UnicornVM-ARMV7(Android)发布初始预览版; 50 | 51 | #### Known Issue 52 | 53 | None. 54 | -------------------------------------------------------------------------------- /UltimateVMP/README.md: -------------------------------------------------------------------------------- 1 | Virtual Machine Protect for iOS/Android native binary file. 2 | 3 | #### Description 4 | 5 | [It's](https://gitee.com/geekneo/UltimateVMP) free for use as a binary analysis tool, but need fee for use as a vmp tool. 6 | 7 | 8 | Follow us for update or bug report: 9 | 10 | |Platform|Account|QRCode| 11 | |-|-|-| 12 | |Email|971159199@qq.com|.| 13 | |公众号|刘柏江|![gongzhonghao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/gongzhonghao.jpeg)| 14 | |百家号|刘柏江VM|![baijiahao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/baijiahao.jpeg)| 15 | |微博|刘柏江VM|![weibo](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/weibo.jpeg)| 16 | |头条|刘柏江|![toutiao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/toutiao.jpeg)| 17 | |码云|https://gitee.com/geekneo/|.| 18 | -------------------------------------------------------------------------------- /UnicornVM-V7/README.md: -------------------------------------------------------------------------------- 1 | Virtual CPU based on unicorn for Android armeabi-v7a. 2 | 3 | #### Description 4 | 5 | * fridobot : test scripts; 6 | * include : c/c++ header for UVM API; 7 | * sample : demo for UVM API; 8 | * solib : UnicornVM's andriod armeabi-v7a runtime; 9 | 10 | ``` 11 | VCAPI long vc_run_interp(const void *fn, const vc_context_t *ctx); 12 | 13 | Run function 'fn' on our VCPU with 'ctx', the return value is in r0 which is the fn's return value. 14 | ``` 15 | 16 | ``` 17 | VCAPI const void *vc_make_callee(const void *fn, void *usrctx, fn_vc_callback_t callback); 18 | 19 | Make a wrapper for function 'fn' with 'usrctx','callback', the return value is a new function pointer which will run under our VCPU; 20 | 21 | You can replace this pointer to process's function pointer like C++-Vtable/Script-Native-Bridge. 22 | ``` 23 | 24 | Follow us for update or bug report: 25 | 26 | |Platform|Account|QRCode| 27 | |-|-|-| 28 | |Email|971159199@qq.com|.| 29 | |公众号|刘柏江|![gongzhonghao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/gongzhonghao.jpeg)| 30 | |百家号|刘柏江VM|![baijiahao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/baijiahao.jpeg)| 31 | |微博|刘柏江VM|![weibo](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/weibo.jpeg)| 32 | |头条|刘柏江|![toutiao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/toutiao.jpeg)| 33 | |码云|https://gitee.com/geekneo/|.| 34 | -------------------------------------------------------------------------------- /UnicornVM-V7/fridobot/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | LOCAL_MODULE := plthooker 6 | LOCAL_SRC_FILES := ../../../Common/PLTHooker/obj/local/armeabi-v7a/libplthooker.a 7 | include $(PREBUILT_STATIC_LIBRARY) 8 | 9 | 10 | include $(CLEAR_VARS) 11 | LOCAL_MODULE := whale 12 | LOCAL_SRC_FILES := ../../../Common/ASMHooker/obj/whale/libwhale.so 13 | include $(PREBUILT_SHARED_LIBRARY) 14 | 15 | 16 | include $(CLEAR_VARS) 17 | LOCAL_MODULE := unicornvm 18 | LOCAL_SRC_FILES := ../../solib/libunicornvm.so 19 | include $(PREBUILT_SHARED_LIBRARY) 20 | 21 | 22 | include $(CLEAR_VARS) 23 | 24 | LOCAL_MODULE := hijackmain 25 | LOCAL_SRC_FILES := hijackmain.cpp 26 | 27 | LOCAL_CFLAGS += -fvisibility=hidden 28 | LOCAL_CPPFLAGS += $(LOCAL_CFLAGS) -std=gnu++14 29 | LOCAL_CONLYFLAGS += -std=gnu99 30 | 31 | LOCAL_LDLIBS += -llog 32 | LOCAL_SHARED_LIBRARIES += unicornvm 33 | LOCAL_STATIC_LIBRARIES += whale 34 | LOCAL_STATIC_LIBRARIES += plthooker 35 | 36 | include $(BUILD_SHARED_LIBRARY) 37 | -------------------------------------------------------------------------------- /UnicornVM-V7/fridobot/jni/Application.mk: -------------------------------------------------------------------------------- 1 | NDK_TOOLCHAIN_VERSION := clang 2 | APP_STL := c++_static 3 | APP_ABI := armeabi-v7a 4 | APP_PLATFORM := android-24 5 | APP_CPPFLAGS := -frtti 6 | -------------------------------------------------------------------------------- /UnicornVM-V7/fridobot/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | This file is used to test UnicornVM android armeabi-v7a library. 4 | 5 | The injected file hijackmain.so will hijack elf's main function 6 | which will run under UnicornVM' virtual cpu context. 7 | 8 | See jni/hijackmain.cpp for more information. 9 | 10 | If you have any advises, We are happy to hear from you. 11 | 12 | 13 | Follow us: 14 | ---------------------------------------------------------------------- 15 | Email 971159199@qq.com 16 | 公众号 刘柏江 17 | 头条 刘柏江 18 | 百家号 刘柏江VM 19 | 微博 刘柏江VM 20 | 码云 https://gitee.com/geekneo/ 21 | ---------------------------------------------------------------------- 22 | ''' 23 | 24 | import os 25 | import sys 26 | import subprocess 27 | 28 | tmpRoot = '/data/local/tmp' 29 | binRoot = tmpRoot + '/LidaDbgServer-arm' 30 | elfPatcher = binRoot + '/elfpatcher' 31 | 32 | def shell(cmds): 33 | print(cmds) 34 | os.system(cmds) 35 | 36 | def execmd(cmdarr): 37 | print(cmdarr) 38 | proc = subprocess.Popen(cmdarr, stdout=subprocess.PIPE) 39 | proc.wait() 40 | return proc.stdout.read() 41 | 42 | def vm_launch(cmdarr, envdict=None): 43 | exepath = cmdarr[0] 44 | if not os.path.exists(exepath): 45 | print('There is no %s.' % (exepath)) 46 | return None 47 | 48 | vmpath = tmpRoot + '/uvm_' + os.path.basename(exepath) 49 | if not os.path.exists(vmpath): 50 | shell('cp -p %s %s; %s --add-needed libhijackmain.so %s' % (exepath, vmpath, elfPatcher, vmpath)) 51 | dtlist = execmd([elfPatcher, '--print-needed', vmpath]) 52 | if dtlist.find('hijackmain') < 0: 53 | shell('rm ' + vmpath) 54 | print('%sFailed to make vm version executable file %s.' % (dtlist, vmpath)) 55 | return None 56 | 57 | if not envdict: 58 | envdict = { 59 | 'LD_LIBRARY_PATH' : binRoot, 60 | } 61 | cmdarr[0] = vmpath 62 | print('ENV: ' + str(envdict)) 63 | print('CMD: ' + str(cmdarr)) 64 | return subprocess.Popen(cmdarr, env=envdict) 65 | 66 | def main(args): 67 | if len(args) == 1: 68 | # set default test program 69 | args = [ 70 | args[0], 71 | elfPatcher, 72 | ] 73 | exepath = args[1] 74 | if not os.path.exists(exepath): 75 | print('%s do not exist.' % (exepath)) 76 | return 77 | vm_launch(args[1:len(args)]).wait() 78 | 79 | if __name__ == '__main__': 80 | main(sys.argv) 81 | -------------------------------------------------------------------------------- /UnicornVM-V7/sample/apitest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | This file is used to test UnicornVM android armeabi-v7a library's API. 4 | 5 | You can run this file using Fridobot. 6 | 7 | If you have any advises, We are happy to hear from you. 8 | 9 | 10 | Follow us: 11 | ---------------------------------------------------------------------- 12 | Email 971159199@qq.com 13 | 公众号 刘柏江 14 | 头条 刘柏江 15 | 百家号 刘柏江VM 16 | 微博 刘柏江VM 17 | 码云 https://gitee.com/geekneo/ 18 | ---------------------------------------------------------------------- 19 | ''' 20 | 21 | import subprocess 22 | 23 | binRoot = '/data/local/tmp/LidaDbgServer-arm' 24 | testBin = binRoot + '/unicornvm_apitest' 25 | 26 | def launch(cmdarr, envdict=None): 27 | if not envdict: 28 | envdict = { 29 | 'LD_LIBRARY_PATH' : binRoot, 30 | } 31 | print(envdict) 32 | print(cmdarr) 33 | return subprocess.Popen(cmdarr, env=envdict) 34 | 35 | if __name__ == '__main__': 36 | launch([testBin]).wait() 37 | -------------------------------------------------------------------------------- /UnicornVM-V7/sample/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | LOCAL_MODULE := unicornvm 6 | LOCAL_SRC_FILES := ../../solib/libunicornvm.so 7 | include $(PREBUILT_SHARED_LIBRARY) 8 | 9 | 10 | include $(CLEAR_VARS) 11 | 12 | LOCAL_MODULE := unicornvm_apitest 13 | LOCAL_SHARED_LIBRARIES := unicornvm 14 | LOCAL_SRC_FILES := ../apitest.cpp 15 | 16 | include $(BUILD_EXECUTABLE) 17 | -------------------------------------------------------------------------------- /UnicornVM-V7/sample/jni/Application.mk: -------------------------------------------------------------------------------- 1 | NDK_TOOLCHAIN_VERSION := clang 2 | APP_STL := c++_static 3 | APP_ABI := armeabi-v7a 4 | APP_PLATFORM := android-21 5 | -------------------------------------------------------------------------------- /UnicornVM-V7/solib/libunicornvm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/UnicornVM-V7/solib/libunicornvm.so -------------------------------------------------------------------------------- /UnicornVM-V8/README.md: -------------------------------------------------------------------------------- 1 | Virtual CPU based on unicorn for Android arm64-v8a. 2 | 3 | #### Description 4 | 5 | * fridobot : test scripts; 6 | * include : c/c++ header for UVM API; 7 | * sample : demo for UVM API; 8 | * solib : UnicornVM's andriod arm64-v8a runtime; 9 | 10 | ``` 11 | VCAPI long vc_run_interp(const void *fn, const vc_context_t *ctx); 12 | 13 | Run function 'fn' on our VCPU with 'ctx', the return value is in x0 which is the fn's return value. 14 | ``` 15 | 16 | ``` 17 | VCAPI const void *vc_make_callee(const void *fn, void *usrctx, fn_vc_callback_t callback); 18 | 19 | Make a wrapper for function 'fn' with 'usrctx','callback', the return value is a new function pointer which will run under our VCPU; 20 | 21 | You can replace this pointer to process's function pointer like C++-Vtable/Script-Native-Bridge. 22 | ``` 23 | 24 | 25 | Follow us for update or bug report: 26 | 27 | |Platform|Account|QRCode| 28 | |-|-|-| 29 | |Email|971159199@qq.com|.| 30 | |公众号|刘柏江|![gongzhonghao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/gongzhonghao.jpeg)| 31 | |百家号|刘柏江VM|![baijiahao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/baijiahao.jpeg)| 32 | |微博|刘柏江VM|![weibo](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/weibo.jpeg)| 33 | |头条|刘柏江|![toutiao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/toutiao.jpeg)| 34 | |码云|https://gitee.com/geekneo/|.| 35 | -------------------------------------------------------------------------------- /UnicornVM-V8/fridobot/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | This file is used to test UnicornVM android arm64-v8a library. 4 | 5 | The injected file hijackmain.so will hijack elf's main function 6 | which will run under UnicornVM' virtual cpu context. 7 | 8 | See jni/hijackmain.cpp for more information. 9 | 10 | If you have any advises, We are happy to hear from you. 11 | 12 | 13 | Follow us: 14 | ---------------------------------------------------------------------- 15 | Email 971159199@qq.com 16 | 公众号 刘柏江 17 | 头条 刘柏江 18 | 百家号 刘柏江VM 19 | 微博 刘柏江VM 20 | 码云 https://gitee.com/geekneo/ 21 | ---------------------------------------------------------------------- 22 | ''' 23 | 24 | import os 25 | import sys 26 | import subprocess 27 | 28 | tmpRoot = '/data/local/tmp' 29 | binRoot = tmpRoot + '/LidaDbgServer-arm64' 30 | elfPatcher = binRoot + '/elfpatcher' 31 | 32 | def shell(cmds): 33 | print(cmds) 34 | os.system(cmds) 35 | 36 | def execmd(cmdarr): 37 | print(cmdarr) 38 | proc = subprocess.Popen(cmdarr, stdout=subprocess.PIPE) 39 | proc.wait() 40 | return proc.stdout.read() 41 | 42 | def vm_launch(cmdarr, envdict=None): 43 | exepath = cmdarr[0] 44 | if not os.path.exists(exepath): 45 | print('There is no %s.' % (exepath)) 46 | return None 47 | 48 | vmpath = tmpRoot + '/uvm_' + os.path.basename(exepath) 49 | if not os.path.exists(vmpath): 50 | shell('cp -p %s %s; %s --add-needed libhijackmain.so %s' % (exepath, vmpath, elfPatcher, vmpath)) 51 | dtlist = execmd([elfPatcher, '--print-needed', vmpath]) 52 | if dtlist.find('hijackmain') < 0: 53 | shell('rm ' + vmpath) 54 | print('%sFailed to make vm version executable file %s.' % (dtlist, vmpath)) 55 | return None 56 | 57 | if not envdict: 58 | envdict = { 59 | 'LD_LIBRARY_PATH' : binRoot, 60 | } 61 | cmdarr[0] = vmpath 62 | print('ENV: ' + str(envdict)) 63 | print('CMD: ' + str(cmdarr)) 64 | return subprocess.Popen(cmdarr, env=envdict) 65 | 66 | def main(args): 67 | if len(args) == 1: 68 | # set default test program 69 | args = [ 70 | args[0], 71 | elfPatcher, 72 | ] 73 | exepath = args[1] 74 | if not os.path.exists(exepath): 75 | print('%s do not exist.' % (exepath)) 76 | return 77 | vm_launch(args[1:len(args)]).wait() 78 | 79 | if __name__ == '__main__': 80 | main(sys.argv) 81 | -------------------------------------------------------------------------------- /UnicornVM-V8/sample/apitest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | This file is used to test UnicornVM android arm64-v8a library's API. 4 | 5 | You can run this file using Fridobot. 6 | 7 | If you have any advises, We are happy to hear from you. 8 | 9 | 10 | Follow us: 11 | ---------------------------------------------------------------------- 12 | Email 971159199@qq.com 13 | 公众号 刘柏江 14 | 头条 刘柏江 15 | 百家号 刘柏江VM 16 | 微博 刘柏江VM 17 | 码云 https://gitee.com/geekneo/ 18 | ---------------------------------------------------------------------- 19 | ''' 20 | 21 | import subprocess 22 | 23 | binRoot = '/data/local/tmp/LidaDbgServer-arm64' 24 | testBin = binRoot + '/unicornvm_apitest' 25 | 26 | def launch(cmdarr, envdict=None): 27 | if not envdict: 28 | envdict = { 29 | 'LD_LIBRARY_PATH' : binRoot, 30 | } 31 | print(envdict) 32 | print(cmdarr) 33 | return subprocess.Popen(cmdarr, env=envdict) 34 | 35 | if __name__ == '__main__': 36 | launch([testBin]).wait() 37 | -------------------------------------------------------------------------------- /UnicornVM-V8/sample/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | include $(CLEAR_VARS) 5 | LOCAL_MODULE := unicornvm 6 | LOCAL_SRC_FILES := ../../solib/libunicornvm.so 7 | include $(PREBUILT_SHARED_LIBRARY) 8 | 9 | 10 | include $(CLEAR_VARS) 11 | 12 | LOCAL_MODULE := unicornvm_apitest 13 | LOCAL_SHARED_LIBRARIES := unicornvm 14 | LOCAL_SRC_FILES := ../apitest.cpp 15 | 16 | include $(BUILD_EXECUTABLE) 17 | -------------------------------------------------------------------------------- /UnicornVM-V8/sample/jni/Application.mk: -------------------------------------------------------------------------------- 1 | NDK_TOOLCHAIN_VERSION := clang 2 | APP_STL := c++_static 3 | APP_ABI := arm64-v8a 4 | APP_PLATFORM := android-21 5 | -------------------------------------------------------------------------------- /UnicornVM-V8/solib/libunicornvm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/UnicornVM-V8/solib/libunicornvm.so -------------------------------------------------------------------------------- /UnicornVM-iOS/README.md: -------------------------------------------------------------------------------- 1 | Virtual CPU based on unicorn for iOS arm64. 2 | 3 | #### Description 4 | 5 | * textobot : test scripts; 6 | * include : c/c++ header for UVM API; 7 | * sample : demo for UVM API; 8 | * dylib : UnicornVM's iOS arm64 runtime; 9 | 10 | ``` 11 | VCAPI long vc_run_interp(const void *fn, const vc_context_t *ctx); 12 | 13 | Run function 'fn' on our VCPU with 'ctx', the return value is in x0 which is the fn's return value. 14 | ``` 15 | 16 | ``` 17 | VCAPI const void *vc_make_callee(const void *fn, void *usrctx, fn_vc_callback_t callback); 18 | 19 | Make a wrapper for function 'fn' with 'usrctx','callback', the return value is a new function pointer which will run under our VCPU; 20 | 21 | You can replace this pointer to process's function pointer like C++-Vtable/Script-Native-Bridge. 22 | ``` 23 | 24 | Follow us for update or bug report: 25 | 26 | |Platform|Account|QRCode| 27 | |-|-|-| 28 | |Email|971159199@qq.com|.| 29 | |公众号|刘柏江|![gongzhonghao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/gongzhonghao.jpeg)| 30 | |百家号|刘柏江VM|![baijiahao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/baijiahao.jpeg)| 31 | |微博|刘柏江VM|![weibo](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/weibo.jpeg)| 32 | |头条|刘柏江|![toutiao](https://gitee.com/geekneo/PantaDocumentRes/raw/master/wemedia/toutiao.jpeg)| 33 | |码云|https://gitee.com/geekneo/|.| 34 | -------------------------------------------------------------------------------- /UnicornVM-iOS/dylib/libunicornvm.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/UnicornVM-iOS/dylib/libunicornvm.dylib -------------------------------------------------------------------------------- /UnicornVM-iOS/sample/makefile: -------------------------------------------------------------------------------- 1 | all: 2 | clang++ -Os -target arm64-apple-ios8.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -o unicornvm_apitest -I../include -L../dylib -lunicornvm -framework Foundation -std=gnu++14 -stdlib=libc++ ./apitest.mm 3 | -------------------------------------------------------------------------------- /UnicornVM-iOS/sample/unicornvm_apitest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heruix/VirtualCode/7e6cbbd157fa357f4ac6f1db3f6092aa849a12dd/UnicornVM-iOS/sample/unicornvm_apitest -------------------------------------------------------------------------------- /UnicornVM-iOS/textobot/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | ''' 3 | This file is used to test UnicornVM iOS arm64 library's API. 4 | 5 | You can run this file using Textobot. 6 | 7 | If you have any advises, We are happy to hear from you. 8 | 9 | 10 | Follow us: 11 | ---------------------------------------------------------------------- 12 | Email 971159199@qq.com 13 | 公众号 刘柏江 14 | 头条 刘柏江 15 | 百家号 刘柏江VM 16 | 微博 刘柏江VM 17 | 码云 https://gitee.com/geekneo/ 18 | ---------------------------------------------------------------------- 19 | ''' 20 | 21 | import sys 22 | import subprocess 23 | 24 | binRoot = '/tmp' 25 | testBin = binRoot + '/unicornvm_apitest' 26 | 27 | def launch(cmdarr): 28 | print(cmdarr) 29 | return subprocess.Popen(cmdarr,stdout=subprocess.PIPE) 30 | 31 | def main(): 32 | proc = launch([testBin]) 33 | proc.wait() 34 | print(proc.stdout.read()) 35 | 36 | main() 37 | --------------------------------------------------------------------------------