Added new documentations files

This commit is contained in:
2022-09-17 14:46:07 +08:00
parent dbd5a74a5c
commit 237d5cbed0
99 changed files with 20686 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
# Usage Example *
::: warning
The current page has not been translated yet.
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
:::

View File

@@ -0,0 +1,186 @@
# Introduce
> This is a Hook API Framework, it does not provide any Hook function itself, it needs the support of basic Xposed API.
## Background
This is an efficient Xposed Hook API rebuilt in `Kotlin`.
The name is taken from ["ももくり" heroine Yuki Kurihara](https://www.bilibili.com/bangumi/play/ss5016).
Formerly the Innocent Xposed API used in [Development Learning Project](https://github.com/fankes/TMore), now renamed and open sourced.
## Usage
`YukiHookAPI` is built entirely with `Kotlin` `lambda` syntax.
Abandoning the original less friendly `XposedHelpers`, you can use it to easily create Xposed Modules and easily implement custom Hook API.
## Language Requirement
Please use `Kotlin`, the framework part of the code composition is also compatible with `Java` but the implementation of the basic Hook scene **may not work at all**.
All demo code in this document will be described using `Kotlin`, if you don't know how to use `Kotlin` then you may not be able to use `YukiHookAPI`.
Part of the Java Demo code can be found [here](https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/java), but not recommended.
## Source of Inspiration
Previously, when we built an Xposed Module, we first needed to create an `xposed_init` file under `assets`.
Then, manually fill in your own entry class name into the file and use `XposedHelpers` to implement our Hook logic.
Since `Kotlin` is the main Android development language, this API is really not very elegant to use.
Is there any **easy to use, light, elegant** solution?
With this idea, `YukiHookAPI` was born.
Now, we only need to write a small amount of code, and all the time and expense are handed over to automation.
With `Kotlin`'s elegant `lambda` writing and `YukiHookAPI`, you can make your Hook logic more beautiful and clear.
> The following example
:::: code-group
::: code-group-item Yuki Hook API
```kotlin
@InjectYukiHookWithXposed
class HookEntry : IYukiHookXposedInit {
override fun onHook() = encase {
loadZygote {
ActivityClass.hook {
injectMember {
method {
name = "onCreate"
param(BundleClass)
}
beforeHook {
// Your code here.
}
afterHook {
// Your code here.
}
}
}
resources().hook {
injectResource {
conditions {
name = "sym_def_app_icon"
mipmap()
}
replaceToModuleResource(R.mipmap.ic_launcher)
}
}
}
loadApp(name = "com.android.browser") {
ActivityClass.hook {
injectMember {
method {
name = "onCreate"
param(BundleClass)
}
beforeHook {
// Your code here.
}
afterHook {
// Your code here.
}
}
}
resources().hook {
injectResource {
conditions {
name = "ic_launcher"
mipmap()
}
replaceToModuleResource(R.mipmap.ic_launcher)
}
}
}
}
}
```
:::
::: code-group-item Xposed API
```kotlin
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
private lateinit var moduleResources: XModuleResources
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
XResources.setSystemWideReplacement(
"android", "mipmap", "sym_def_app_icon",
moduleResources.fwd(R.mipmap.ic_launcher)
)
XposedHelpers.findAndHookMethod(
Activity::class.java.name,
null, "onCreate",
Bundle::class.java,
object : XC_MethodHook() {
override fun beforeHookedMethod(param: MethodHookParam?) {
// Your code here.
}
override fun afterHookedMethod(param: MethodHookParam?) {
// Your code here.
}
})
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
if (lpparam.packageName == "com.android.browser")
XposedHelpers.findAndHookMethod(
Activity::class.java.name,
lpparam.classLoader, "onCreate",
Bundle::class.java,
object : XC_MethodHook() {
override fun beforeHookedMethod(param: MethodHookParam?) {
// Your code here.
}
override fun afterHookedMethod(param: MethodHookParam?) {
// Your code here.
}
})
}
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
if (resparam.packageName == "com.android.browser")
resparam.res.setReplacement(
"com.android.browser", "mipmap", "ic_launcher",
moduleResources.fwd(R.mipmap.ic_launcher)
)
}
}
```
:::
::::
Yes, you read that right, just needing these codes can completely replace the Xposed API to achieve the same function.
Now, with the help of the efficient and powerful `YukiHookAPI`, you can implement a very simple Xposed Module.
## Suppored Hook Framework
The following are the `Hook Framework` and Xposed framework supported by `YukiHookAPI`.
| Hook Framework | ST | Description |
| --------------------------------------------------------- | --- | ----------------------------------------------------------------------------------------- |
| [LSPosed](https://github.com/LSPosed/LSPosed) | ✅ | Stable use in multiple scenarios |
| [LSPatch](https://github.com/LSPosed/LSPatch) | ⭕ | WIP after this project is improved |
| [EdXposed](https://github.com/ElderDrivers/EdXposed) | ❎ | Maintenance has stopped, no longer recommended |
| [Pine](https://github.com/canyie/pine) | ⭕ | Only available |
| [SandHook](https://github.com/asLody/SandHook) | ⭕ | Only available |
| [Whale](https://github.com/asLody/whale) | ⭕ | Need [xposed-hook-based-on-whale](https://github.com/WindySha/xposed-hook-based-on-whale) |
| [YAHFA](https://github.com/PAGalaxyLab/YAHFA) | ❗ | Need to implement the Xposed API yourself |
| [FastHook](https://github.com/turing-technician/FastHook) | ❗ | Need to implement the Xposed API yourself |
| [Epic](https://github.com/tiann/epic) | ❗ | Need [Dexposed](https://github.com/alibaba/dexposed) by yourself |
| [TaiChi](https://github.com/taichi-framework/TaiChi) | ⭕ | Only available for Xposed Module |
| [Xposed](https://github.com/rovo89/Xposed) | ❎ | Not test, no longer recommended |

View File

@@ -0,0 +1,89 @@
# Basic Knowledge
> Here is a collection of Xposed-related introductions and the key points of knowledge that need to be grasped before start.
>
> Anyone who already knows can skip it.
The basic knowledge content <u>**not necessarily completely accurate**</u>, please read it according to your own opinion.
If you find **any errors in this page, please correct it and help us improve**.
## Related Introduction
> Here's an introduction to Xposed and how Hooks work.
### What is Xposed
> Xposed Framework (Xposed Framework) is a set of open source framework services that run in Android high-privilege mode. It can affect program operation (modify the system) without modifying the APK file. Based on it, many Powerful modules that operate simultaneously without conflicting functions.
The above content is copied from Baidu Encyclopedia.
### What can Xposed do
> The structure below describes the basic workings and principles of Xposed.
```:no-line-numbers
Xposed Framework
└── App's Environment
└── Hooker (Hooked)
...
App's Environment
└── Hooker (Hooked)
...
...
```
We can achieve the ultimate goal of controlling its behavior by injecting the **Host (App)** when the **Host (App)** is running.
This mode of operation of Xposed is called **parasitism**. The Xposed Module follows the lifecycle of the host and completes its own life course within the lifecycle of the **Host**.
We can call the **Host**'s methods, fields, and constructors through reflection, and use the Hook operation provided by `XposedBridge` to dynamically insert our own code before and after the method to be executed by the **Host (App)**, or completely replace the target, or even intercept.
### Development Process
Today's Xposed Manager has been completely replaced by its derivative works, and the era of **SuperSU** has ended, and now, with **Magisk**, everything behind is possible again.
> Its development history can be roughly divided into **Xposed(Dalvik)** → **Xposed(ART)** → **Xposed(Magisk)** → **EdXposed(Riru)**/**LSPosed(Riru/ Zygisk)**
### Derivatives
> The structure below describes how and how the Xposed-like Hook Framework works.
```:no-line-numbers
App's Environment
└── Hook Framework
└── Hooker (Hooked)
...
```
Through the operation principle of Xposed, many frameworks of the same type have been derived. As mobile devices in today's era are more and more difficult to obtain Root permissions or even flash, and when they are not just needed, some Root-free frameworks are also produced, such as **Tai Chi**.
These Hook Frameworks at the ART level can also complete the Hook process with the same principle as Xposed without using the Xposed API. The operating principle of Root-free is to modify the APK and inject the Hook process into the **Host**, and control it through external modules.
Another product is to use the existing functions of the Android operating environment to virtualize an environment that is completely the same as the current device system, and run App in it. This is the virtual App technology **VirtualApp**, which was later derived as **VirtualXposed** .
The Root-free frameworks mentioned above are **Tai Chi/Wuji**, **VirtualXposed/SandVXposed**.
### What YukiHookAPI does
Since Xposed appeared until now, apart from `XposedHelpers`, which is well known to developers, there is still no set of syntactic sugar for `Kotlin` and API with complete usage encapsulation.
The birth of this API framework is to hope that in the current era of Xposed, more capable Xposed Module developers can avoid detours and complete the entire development process more easily and simply.
In the future, `YukiHookAPI` will adapt to more third-party Hook Frameworks based on the goal of using the Xposed API, so as to improve the entire ecosystem and help more developers make Xposed Module development simpler and easier to understand.
## Let's Started
Before starting, you need to have the following basics to better use `YukiHookAPI`.
- Grasp and understand Android development and simple system operation principles
- To grasp and understand the internal structure of Android APK and simple decompilation knowledge, you can refer to [Jadx](https://github.com/skylot/jadx) and [ApkTool](https://github.com/iBotPeaches/Apktool)
- Grasp and proficient in using Java reflection, understand simple Smali syntax, understand Dex file structure, and use reverse analysis to locate method locations
- Grasp the basic native [Xposed API](https://api.xposed.info) usage, understand the operation principle of Xposed
- Grasp Kotlin language and learn to use **Kotlin lambda**
- Grasp and understand Kotlin and Java mixing, calling each other, and Java bytecode generated by Kotlin

View File

@@ -0,0 +1,259 @@
# Migrate from Xposed API
> If you are familiar with Xposed API, you can refer to the same point below to quickly migrate your API to `YukiHookAPI`.
## Migrate Hook Entry Point
> Migrated from `XC_LoadPackage.LoadPackageParam` to `PackageParam`.
`YukiHookAPI` implements the `lambda` method body `this` usage for `PackageParam`, and the `PackageParam` object can be obtained globally in the `encase` method body.
> The API function differences are compared as follows
:::: code-group
::: code-group-item Yuki Hook API
```kotlin
override fun onHook() = encase {
// Get the package name of the current Hook
packageName
// Get the ApplicationInfo of the current Hook
appInfo
// Get the system context object
systemContext
// Get the host Application lifecycle
appContext
// Hook specified app
loadApp(name = "com.demo.test") {
// Class Hook
findClass("com.demo.test.TestClass").hook {
injectMember {
method {
name = "test"
param(BooleanType)
}
afterHook {
// ...
}
}
}
// Resources Hook (fixed usage)
resources().hook {
injectResource {
conditions {
name = "ic_launcher"
mipmap()
}
replaceToModuleResource(R.mipmap.ic_launcher)
}
}
}
}
```
:::
::: code-group-item Xposed API
```kotlin
private lateinit var moduleResources: XModuleResources
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
// Get the package name of the current Hook
lpparam.packageName
// Get the ApplicationInfo of the current Hook
lpparam.applicationInfo
// Get the system context object
// There is no ready-made calling method in the native Xposed API, you need to reflect ActivityThread to achieve it
// Get the host Application lifecycle
AndroidAppHelper.currentApplication()
// Class Hook
if(lpparam.packageName == "com.demo.test")
XposedHelpers.findAndHookMethod(
"com.demo.test.TestClass", lpparam.classLoader,
"test", Boolean::class.java,
object : XC_MethodHook() {
override fun afterHookedMethod(param: MethodHookParam) {
// ...
}
}
)
}
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
// Get the package name of the current Hook
resparam.packageName
// Resources Hook
resparam.res.setReplacement(
"com.demo.test", "mipmap", "ic_launcher",
moduleResources.fwd(R.mipmap.ic_launcher)
)
}
```
:::
::::
## Migrate Hook Method Body
> Migrated from `XC_MethodHook.MethodHookParam` to `HookParam`.
### Before/After Hook
`YukiHookAPI` also implements the `lambda` method body `this` usage for `HookParam`, and the `HookParam` object can be obtained globally in the method bodies such as `beforeHook` and `afterHook`.
> The API function differences are compared as follows
:::: code-group
::: code-group-item Yuki Hook API
```kotlin
afterHook {
// Get the current Hook instance
instance
// Get the Class instance of the current Hook
instanceClass
// Get and cast the current Hook instance to the specified type T
instance<T>()
// Get the method parameter array
args
// Get the first T of the method parameter
args().first().cast<T>()
// Get the last bit of the method parameter T
args().last().cast<T>()
// Get any subscript T of the method parameter, here is an example of 2
args(index = 2).cast<T>()
// Set any subscript of the method parameter, here is an example of 2
args(index = 2).set(...)
// Get the return value
result
// Get the return value and cast to T
result<T>()
// Modify the content of the return value
result = ...
// Remove the content of the return value
resultNull()
// Throw an exception to the Hook app
Throwable("Fatal").throwToApp()
// Execute the original method without hook and call with the original method parameters, generics can be omitted
callOriginal<Any?>()
// Execute the original method without Hook and customize the method parameter call, the generic type can be omitted
invokeOriginal<Any?>(...)
}
```
:::
::: code-group-item Xposed API
```kotlin
override fun afterHookedMethod(param: MethodHookParam) {
// Get the current Hook instance
param.thisObject
// Get the Class instance of the current Hook
param.thisObject.javaClass
// Get and cast the current Hook instance to the specified type T
param.thisObject as T
// Get the method parameter array
param.args
// Get the first T of the method parameter
param.args[0] as T
// Get the last bit of the method parameter T
param.args[param.args.lastIndex] as T
// Get any subscript T of the method parameter, here is an example of 2
param.args[2] as T
// Set any subscript of the method parameter, here is an example of 2
param.args[2] = ...
// Get the return value
param.result
// Get the return value and cast to T
param.result as T
// Modify the content of the return value
param.result = ...
// Remove the content of the return value
param.result = null
// Throw an exception to the Hook app
param.throwable = Throwable("Fatal")
// Execute the original method without hooking
XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
}
```
:::
::::
### Replace Hook
The `replaceHook` method is special, and the `YukiHookAPI` makes a variety of forms for it to choose from.
> The API function differences are compared as follows
:::: code-group
::: code-group-item Yuki Hook API
```kotlin
/// A method with no return value void
replaceUnit {
// Implement the replaced logic directly here
}
/// A method with a return value
replaceAny {
// Implement the replaced logic here
// ...
// Need to return the return value corresponding to the method, no need to write return, just put the parameter in the last digit
// Assuming the return value of this method is an Int, we just need to ensure that the last bit is the return value we need
0
}
/// For some methods, we just need to replace their return value, then there are the following implementations
/// It should be noted that the parameters passed in by the method of directly replacing the return value are fixed. If you want to dynamically replace the return value, please use the above replaceAny method body
// Replace with the return value you need
replaceTo(...)
// Replace with return value of type Boolean
replaceToTrue()
// Intercept return value
intercept()
```
:::
::: code-group-item Xposed API
```kotlin
/// A method with no return value void
override fun replaceHookedMethod(param: MethodHookParam): Any? {
// Implement the replaced logic directly here
return null
}
/// A method with a return value
override fun replaceHookedMethod(param: MethodHookParam): Int {
// Implement the replaced logic here
// ...
// Assume the return value of this method is an Int
return 0
}
/// For some methods, we just need to replace their return value, then there are the following implementations
// Replace with the return value you need
override fun replaceHookedMethod(param: MethodHookParam) = ...
// Replace with return value of type Boolean
override fun replaceHookedMethod(param: MethodHookParam) = true
// Intercept return value
override fun replaceHookedMethod(param: MethodHookParam) = null
```
:::
::::
## Migrate Other Features
`YukiHookAPI` is a complete rewrite of the Xposed API, you can refer to [API Document](../api/home) and [Special Features](../api/special-features/reflection) to determine some functional Migration and use.

View File

@@ -0,0 +1,208 @@
# Quick Start
> Integrate `YukiHookAPI` into your project.
## Environment Requirements
- Windows 7 and above / macOS 10.14 and above / Linux distributions (Arch/Debian)
- Android Studio 2021.1 and above
- IntelliJ IDEA 2021.1 and above
- Kotlin 1.7.0 and above
- Android Gradle Plugin 7.0 and above
- Gradle 7.0 and above
- JVM 11 and above (Since API `1.0.80`)
## Automatically build the project
`YukiHookAPI` provides an automated build tool that can help you quickly build an Android standard project template with Xposed Module dependencies, and use the built template to start the next step directly.
You can [click here](../tools/yukihookapi-projectbuilder) to check it out.
## Manually configure the project
If you don't want to use automated build tools, you can still manually configure project dependencies as follows.
### Create Project
Use `Android Studio` or `IntelliJ IDEA` to create a new Android project and select `Kotlin` in the `Language` column to automatically add basic dependencies.
### Integration Dependencies
Add dependencies to your project `build.gradle`.
> The following example
```groovy
repositories {
google()
mavenCentral()
// ❗If your Plugin version is too low, be sure to add it as an Xposed Module, other cases are optional
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
// ❗Be sure to add it as an Xposed Module, optional in other cases
maven { url "https://api.xposed.info/" }
// MavenCentral has a 2-hour cache, if you cannot integrate the latest version, please add this address
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
}
```
Add `plugin` to your app `build.gradle`.
> The following example
```groovy
plugins {
// ❗Be sure to add it as an Xposed Module, optional in other cases
id 'com.google.devtools.ksp' version '<ksp-version>'
}
```
Add dependencies to your app `build.gradle`.
> The following example
```groovy
dependencies {
// base dependencies
implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
// ❗Be sure to add it as an Xposed Module, optional in other cases
compileOnly 'de.robv.android.xposed:api:82'
// ❗Be sure to add it as an Xposed Module, optional in other cases
ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
}
```
Please modify **&lt;ksp-version&gt;** to the latest version from [here](https://github.com/google/ksp/releases) **(Please choose your current corresponding Kotlin version)**.
Please modify **&lt;yuki-version&gt;** to the latest version [here](../about/changelog).
::: danger
The **api** of **YukiHookAPI** and the versions that **ksp-xposed** depend on must correspond one by one, otherwise a version mismatch error will occur.
:::
Modify the JVM version of `Kotlin` to 11 and above in your app `build.gradle`.
> The following example
```groovy
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '11'
}
}
```
::: warning
Since API **1.0.80** version, the default JVM version is 11, and 1.8 and below are no longer supported.
:::
### Use as Xposed Module
Add the base code to your `AndroidManifest.xml`.
> The following example
```xml
<!-- Set as Xposed Module -->
<meta-data
android:name="xposedmodule"
android:value="true" />
<!-- set your module description -->
<meta-data
android:name="xposeddescription"
android:value="Fill in your Xposed Module description" />
<!-- The minimum Xposed version number, if you are using EdXposed/LSPosed, the minimum recommended is 93 -->
<meta-data
android:name="xposedminversion"
android:value="93" />
<!-- Optional: configure support for New XSharePrefs without adjusting xposedminversion to 93 -->
<meta-data
android:name="xposedsharedprefs"
android:value="true"/>
```
Create a Hook entry class in your project, inherit from `IYukiHookXposedInit` and add the annotation `@InjectYukiHookWithXposed`.
> The following example
```kotlin
@InjectYukiHookWithXposed
class HookEntry : IYukiHookXposedInit {
override fun onHook() = YukiHookAPI.encase {
// Your code here.
}
}
```
::: tip Suggestion
You can inherit **Application** of your module app from **ModuleApplication** to achieve a complete user experience.
For more functions, please refer to [ModuleApplication](../api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication).
:::
Then, you can start writing Hook code.
For configuration details related to use as an Xposed Module, you can [click here](../config/xposed-using) to continue reading.
If you are currently using Xposed API, you can refer to [Migrating from Xposed API](../guide/move-to-new-api).
### Use as Hook API
#### Integration
Create your custom `Application`.
::: danger
Regardless of the **Hook Framework** you use, you need to add its docking Xposed dependency support.
If the target **Hook Framework** does not integrate Xposed API, you need to implement and connect **XposedBridge** by yourself.
:::
Add `YukiHookAPI.encase` method to `attachBaseContext`.
> The following example
```kotlin
override fun attachBaseContext(base: Context?) {
// Load Hook Framework
//
// Your code here.
//
// Load YukiHookAPI
YukiHookAPI.encase(base) {
// Your code here.
}
super.attachBaseContext(base)
}
```
Then, you can start writing Hook code in much the same way you would use it as an Xposed Module.
For configuration details related to use as a Hook API, you can [click here](../config/api-using) to continue reading.
::: warning
**YukiHookModuleStatus**, **YukiHookModulePrefs**, **YukiHookDataChannel** and Resources Hook functionality will not work when using a custom Hook Framework instead of the full Xposed Module.
:::