Skip to content

Commit

Permalink
接下来要写自己的库,故准备好一系列重建
Browse files Browse the repository at this point in the history
  • Loading branch information
EarzuChan committed Aug 15, 2024
1 parent 56ae519 commit 0a47aaf
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
chmod +x .scripts/setup_docker.sh
- name: 为 ${{ matrix.cross }} 注册米哈游通行证
run: ./gradlew build
- name: (${{ matrix.cross }}) 成为米孝子的第一天捏
- name: 是 ${{ matrix.cross }} 成为米孝子的第一天捏
run: .scripts/setup_docker.sh
env:
CROSS: ${{ matrix.cross }}
Expand Down
32 changes: 21 additions & 11 deletions api/src/main/kotlin/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ package me.earzuchan.sakiko.api

import java.lang.reflect.Method

// 神金
fun <T> getNIL(): T? {
return null
}
const val 文本 = "度尽劫波兄弟在,相逢一笑泯恩仇"

inline fun NIL(): Nothing = throw NullPointerException(文本)

public abstract class SakikoBridge {
abstract fun hook(method: Method, config: HookConfig)
Expand All @@ -14,10 +13,8 @@ public abstract class SakikoBridge {

companion object {
@JvmStatic
var INSTANCE: SakikoBridge? = getNIL()
var INSTANCE: SakikoBridge = NIL()
}


}

public abstract class SakikoBaseModule {
Expand All @@ -27,20 +24,21 @@ public abstract class SakikoBaseModule {
fun Method.hook(configure: HookConfig.() -> Unit): UnhookConfig {
val config = HookConfig().apply(configure)

SakikoBridge.INSTANCE!!.hook(this, config)
SakikoBridge.INSTANCE.hook(this, config)

return UnhookConfig(this)
}

class UnhookConfig(private val method: Method) {
fun unhook() {
SakikoBridge.INSTANCE!!.unhook(method)
SakikoBridge.INSTANCE.unhook(method)
}
}

class HookConfig {
var beforeLambda: (HookContext.() -> Unit)? = null
var afterLambda: (HookContext.() -> Unit)? = null
var replaceLambda: (HookContext.() -> Any?)? = null

fun before(action: HookContext.() -> Unit) {
beforeLambda = action
Expand All @@ -49,8 +47,20 @@ class HookConfig {
fun after(action: HookContext.() -> Unit) {
afterLambda = action
}
}

class HookContext(val args: Array<Any?>) {
fun replaceAny(action: HookContext.() -> Any?) {
replaceLambda = action
}

fun replaceUnit(action: HookContext.() -> Unit) {
replaceLambda = action
}

fun replaceTo(value: Any?) {
replaceLambda = { value }
}
}

class HookContext(val args: Array<Any?>, val instance: Any) {
var result: Any? = null
}
66 changes: 59 additions & 7 deletions api/src/main/kotlin/Reflecting.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,73 @@
package me.earzuchan.sakiko.api.reflecting

import me.earzuchan.sakiko.api.HookConfig
import me.earzuchan.sakiko.api.UnhookConfig
import me.earzuchan.sakiko.api.hook
import java.lang.reflect.Method

fun Class<*>.method(configure: MethodConfig.() -> Unit): Method {
val config = MethodConfig().apply(configure)
return this.getDeclaredMethod(config.name, *config.params.toTypedArray())
fun Class<*>.method(configure: MethodMatchConfig.() -> Unit): MethodMatches {
val config = MethodMatchConfig().apply(configure)
val methods = this.declaredMethods.filter { it.name == config.name }

return if (config.paramsHasSet) {
// 方法类型匹配
MethodMatches(methods.filter { it.parameterTypes.contentEquals(config.params.toTypedArray()) })
} else {
MethodMatches(methods)
}
}

// 方法匹配器
class MethodMatches(private val methods: List<Method>) {
// 选择仅一个方法
fun hook(configure: HookConfig.() -> Unit): UnhookConfig {
if (methods.size == 1) {
return methods[0].hook(configure)
} else {
throw IllegalStateException("Multiple methods found. Use all() to select specific methods.")
}
}

// 选择所有方法
fun all(): List<Method> {
return methods
}
}

class MethodConfig {
// 批量 hook
fun List<Method>.hook(configure: HookConfig.() -> Unit): List<UnhookConfig> = map { it.hook(configure) }

// 方法匹配配置
class MethodMatchConfig {
lateinit var name: String
val params = mutableListOf<Class<*>>()
var paramsHasSet = false

fun param(vararg givenParams: Class<*>) {
if (paramsHasSet) {
throw IllegalStateException("Params has been set")
}
params.addAll(givenParams)
paramsHasSet = true
}

fun param(param: Class<*>) {
params.add(param)
fun emptyParam() {
param()
}
}

// 简便化的类名匹配
fun String.toClass(): Class<*> {
return Class.forName(this)
}
}

val StringClass = String::class.java
val IntType = Int::class.javaPrimitiveType
val LongType = Long::class.javaPrimitiveType
val FloatType = Float::class.javaPrimitiveType
val DoubleType = Double::class.javaPrimitiveType
val BooleanType = Boolean::class.javaPrimitiveType
val ByteType = Byte::class.javaPrimitiveType
val ShortType = Short::class.javaPrimitiveType
val CharType = Char::class.javaPrimitiveType
val UnitType = Unit::class.javaPrimitiveType
10 changes: 5 additions & 5 deletions core/src/main/kotlin/Core.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package me.earzuchan.sakiko.core

import me.earzuchan.sakiko.api.HookConfig
import me.earzuchan.sakiko.api.HookContext
import me.earzuchan.sakiko.api.SakikoBaseModule
import me.earzuchan.sakiko.api.SakikoBridge
import me.earzuchan.sakiko.core.util.Log
Expand All @@ -10,12 +9,12 @@ import java.lang.reflect.Method
const val TAG = "SakikoCore"

// Karlatemp圣千古
object KarlatempNativeCompat {
external fun initNative(): Boolean
object KarlatempCompat {
fun initNative(): Boolean = true
}

object Runner {
fun runModule(module: SakikoBaseModule) {
fun loadModule(module: SakikoBaseModule) {
module.onHook()
}

Expand All @@ -27,14 +26,15 @@ object Runner {
}

private fun ensureNative() {
if (!KarlatempNativeCompat.initNative()) {
if (!KarlatempCompat.initNative()) {
throw UnsatisfiedLinkError("Native library status is not OK")
}

Log.debug(TAG, "Native library loaded")
}

private fun ensureBridge() {
// 通过反射设置INSTANCE以绕过Exception抛出
SakikoBridge.INSTANCE = SakikoKarlatempBridge()
Log.debug(TAG, "Bridge initialized")
}
Expand Down
20 changes: 10 additions & 10 deletions loader/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ tasks.register<Jar>("agentJar") {
}

tasks.register<JavaExec>("testLoader") {
dependsOn(":buildNativeOnMyPc")
// dependsOn(":buildNativeOnMyPc")

classpath = sourceSets.main.get().runtimeClasspath
mainClass.set("me.earzuchan.sakiko.loader.LoaderEntry")

doFirst {
val nativeLibDir = file("${project.rootDir}/native-old/build")
val nativeLib = nativeLibDir.listFiles()?.firstOrNull { it.extension == "dll" || it.extension == "so" }
// val nativeLibDir = file("${project.rootDir}/native-old/build")
// val nativeLib = nativeLibDir.listFiles()?.firstOrNull { it.extension == "dll" || it.extension == "so" }
val agentJar = tasks.named<Jar>("agentJar").get().archiveFile.get().asFile

if (nativeLib != null) {
println("找到本机库: ${nativeLib.absolutePath}")
val myArgs = arrayOf("-agentpath:${nativeLib.absolutePath}", "-javaagent:${agentJar.absolutePath}")
println("JVM参数: ${myArgs.joinToString { it }}")
jvmArgs(*myArgs)
} else {
/*if (nativeLib != null) {
println("找到本机库: ${nativeLib.absolutePath}")*/
val myArgs = arrayOf(/*"-agentpath:${nativeLib.absolutePath}",*/ "-javaagent:${agentJar.absolutePath}")
println("JVM参数: ${myArgs.joinToString { it }}")
jvmArgs(*myArgs)
/*} else {
throw GradleException("没找到位于${nativeLibDir}的本机库")
}
}*/
}
}
6 changes: 3 additions & 3 deletions loader/src/main/kotlin/Loader.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package me.earzuchan.sakiko.loader

import me.earzuchan.sakiko.api.SakikoBaseModule
import me.earzuchan.sakiko.api.hook
import me.earzuchan.sakiko.api.reflecting.StringClass
import me.earzuchan.sakiko.api.reflecting.method
import me.earzuchan.sakiko.api.reflecting.toClass
import me.earzuchan.sakiko.core.Runner
Expand All @@ -16,11 +16,11 @@ object LoaderEntry {
Log.info(TAG, "Premain")

with(Runner) {
runModule(object : SakikoBaseModule() {
loadModule(object : SakikoBaseModule() {
override fun onHook() {
"me.earzuchan.sakiko.loader.LoaderEntry".toClass().method {
name = "test"
param(String::class.java)
param(StringClass)
}.hook {
before {
println("Before hook")
Expand Down
Empty file added native/CMakeLists.txt
Empty file.

0 comments on commit 0a47aaf

Please sign in to comment.