├── .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